diff --git a/prompto-lab-app/SF-Chain/pom.xml b/prompto-lab-app/SF-Chain/pom.xml new file mode 100644 index 0000000..ff5f646 --- /dev/null +++ b/prompto-lab-app/SF-Chain/pom.xml @@ -0,0 +1,180 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.14 + + + + com.suifeng + sf-chain + 1.0.0 + jar + SF-Chain Framework + SF-Chain AI Framework - A reusable AI operation framework + + + 17 + 17 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-webflux + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + org.springframework.boot + spring-boot-autoconfigure + + + + + org.projectlombok + lombok + true + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.springframework + spring-aspects + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.junit.jupiter + junit-jupiter + test + + + + + com.vladmihalcea + hibernate-types-52 + 2.21.1 + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.40 + + + + + com.mysql + mysql-connector-j + runtime + + + + + org.postgresql + postgresql + runtime + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.boot + spring-boot-configuration-processor + 2.7.14 + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + + copy-frontend-resources + process-resources + + copy-resources + + + ${project.build.outputDirectory}/static + + + src/main/frontend/dist + false + + + + + + + + + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.editorconfig b/prompto-lab-app/SF-Chain/src/main/frontend/.editorconfig new file mode 100644 index 0000000..5a5809d --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.editorconfig @@ -0,0 +1,9 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +end_of_line = lf +max_line_length = 100 diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.gitattributes b/prompto-lab-app/SF-Chain/src/main/frontend/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.gitignore b/prompto-lab-app/SF-Chain/src/main/frontend/.gitignore new file mode 100644 index 0000000..8ee54e8 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.prettierrc.json b/prompto-lab-app/SF-Chain/src/main/frontend/.prettierrc.json new file mode 100644 index 0000000..29a2402 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "singleQuote": true, + "printWidth": 100 +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/_metadata.json b/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/_metadata.json new file mode 100644 index 0000000..81b3959 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/_metadata.json @@ -0,0 +1,31 @@ +{ + "hash": "09d8b648", + "configHash": "bfd8a383", + "lockfileHash": "ca82ab84", + "browserHash": "0deaf2f1", + "optimized": { + "vue": { + "src": "../../node_modules/vue/dist/vue.runtime.esm-bundler.js", + "file": "vue.js", + "fileHash": "12257286", + "needsInterop": false + }, + "pinia": { + "src": "../../node_modules/pinia/dist/pinia.mjs", + "file": "pinia.js", + "fileHash": "93a896c9", + "needsInterop": false + }, + "vue-router": { + "src": "../../node_modules/vue-router/dist/vue-router.mjs", + "file": "vue-router.js", + "fileHash": "a0b9ef41", + "needsInterop": false + } + }, + "chunks": { + "chunk-IDACCYAP": { + "file": "chunk-IDACCYAP.js" + } + } +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/chunk-IDACCYAP.js b/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/chunk-IDACCYAP.js new file mode 100644 index 0000000..e143287 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/.vite/deps/chunk-IDACCYAP.js @@ -0,0 +1,12619 @@ +// node_modules/@vue/shared/dist/shared.esm-bundler.js +function makeMap(str) { + const map2 = /* @__PURE__ */ Object.create(null); + for (const key of str.split(",")) map2[key] = 1; + return (val) => val in map2; +} +var EMPTY_OBJ = true ? Object.freeze({}) : {}; +var EMPTY_ARR = true ? Object.freeze([]) : []; +var NOOP = () => { +}; +var NO = () => false; +var isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter +(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); +var isModelListener = (key) => key.startsWith("onUpdate:"); +var extend = Object.assign; +var remove = (arr, el) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } +}; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var hasOwn = (val, key) => hasOwnProperty.call(val, key); +var isArray = Array.isArray; +var isMap = (val) => toTypeString(val) === "[object Map]"; +var isSet = (val) => toTypeString(val) === "[object Set]"; +var isDate = (val) => toTypeString(val) === "[object Date]"; +var isRegExp = (val) => toTypeString(val) === "[object RegExp]"; +var isFunction = (val) => typeof val === "function"; +var isString = (val) => typeof val === "string"; +var isSymbol = (val) => typeof val === "symbol"; +var isObject = (val) => val !== null && typeof val === "object"; +var isPromise = (val) => { + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); +}; +var objectToString = Object.prototype.toString; +var toTypeString = (value) => objectToString.call(value); +var toRawType = (value) => { + return toTypeString(value).slice(8, -1); +}; +var isPlainObject = (val) => toTypeString(val) === "[object Object]"; +var isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; +var isReservedProp = makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" +); +var isBuiltInDirective = makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); +var cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +}; +var camelizeRE = /-(\w)/g; +var camelize = cacheStringFunction( + (str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); + } +); +var hyphenateRE = /\B([A-Z])/g; +var hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() +); +var capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}); +var toHandlerKey = cacheStringFunction( + (str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; + } +); +var hasChanged = (value, oldValue) => !Object.is(value, oldValue); +var invokeArrayFns = (fns, ...arg) => { + for (let i = 0; i < fns.length; i++) { + fns[i](...arg); + } +}; +var def = (obj, key, value, writable = false) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + writable, + value + }); +}; +var looseToNumber = (val) => { + const n = parseFloat(val); + return isNaN(n) ? val : n; +}; +var toNumber = (val) => { + const n = isString(val) ? Number(val) : NaN; + return isNaN(n) ? val : n; +}; +var _globalThis; +var getGlobalThis = () => { + return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); +}; +var GLOBALS_ALLOWED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol"; +var isGloballyAllowed = makeMap(GLOBALS_ALLOWED); +function normalizeStyle(value) { + if (isArray(value)) { + const res = {}; + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item); + if (normalized) { + for (const key in normalized) { + res[key] = normalized[key]; + } + } + } + return res; + } else if (isString(value) || isObject(value)) { + return value; + } +} +var listDelimiterRE = /;(?![^(]*\))/g; +var propertyDelimiterRE = /:([^]+)/; +var styleCommentRE = /\/\*[^]*?\*\//g; +function parseStringStyle(cssText) { + const ret = {}; + cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => { + if (item) { + const tmp = item.split(propertyDelimiterRE); + tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); + } + }); + return ret; +} +function stringifyStyle(styles) { + if (!styles) return ""; + if (isString(styles)) return styles; + let ret = ""; + for (const key in styles) { + const value = styles[key]; + if (isString(value) || typeof value === "number") { + const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); + ret += `${normalizedKey}:${value};`; + } + } + return ret; +} +function normalizeClass(value) { + let res = ""; + if (isString(value)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); +} +function normalizeProps(props) { + if (!props) return null; + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); + } + if (style) { + props.style = normalizeStyle(style); + } + return props; +} +var HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; +var SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; +var MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; +var VOID_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr"; +var isHTMLTag = makeMap(HTML_TAGS); +var isSVGTag = makeMap(SVG_TAGS); +var isMathMLTag = makeMap(MATH_TAGS); +var isVoidTag = makeMap(VOID_TAGS); +var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; +var isSpecialBooleanAttr = makeMap(specialBooleanAttrs); +var isBooleanAttr = makeMap( + specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected` +); +function includeBooleanAttr(value) { + return !!value || value === ""; +} +var isKnownHtmlAttr = makeMap( + `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap` +); +var isKnownSvgAttr = makeMap( + `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan` +); +var isKnownMathMLAttr = makeMap( + `accent,accentunder,actiontype,align,alignmentscope,altimg,altimg-height,altimg-valign,altimg-width,alttext,bevelled,close,columnsalign,columnlines,columnspan,denomalign,depth,dir,display,displaystyle,encoding,equalcolumns,equalrows,fence,fontstyle,fontweight,form,frame,framespacing,groupalign,height,href,id,indentalign,indentalignfirst,indentalignlast,indentshift,indentshiftfirst,indentshiftlast,indextype,justify,largetop,largeop,lquote,lspace,mathbackground,mathcolor,mathsize,mathvariant,maxsize,minlabelspacing,mode,other,overflow,position,rowalign,rowlines,rowspan,rquote,rspace,scriptlevel,scriptminsize,scriptsizemultiplier,selection,separator,separators,shift,side,src,stackalign,stretchy,subscriptshift,superscriptshift,symmetric,voffset,width,widths,xlink:href,xlink:show,xlink:type,xmlns` +); +function isRenderableAttrValue(value) { + if (value == null) { + return false; + } + const type = typeof value; + return type === "string" || type === "number" || type === "boolean"; +} +var cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g; +function getEscapedCssVarName(key, doubleEscape) { + return key.replace( + cssVarNameEscapeSymbolsRE, + (s) => doubleEscape ? s === '"' ? '\\\\\\"' : `\\\\${s}` : `\\${s}` + ); +} +function looseCompareArrays(a, b) { + if (a.length !== b.length) return false; + let equal = true; + for (let i = 0; equal && i < a.length; i++) { + equal = looseEqual(a[i], b[i]); + } + return equal; +} +function looseEqual(a, b) { + if (a === b) return true; + let aValidType = isDate(a); + let bValidType = isDate(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? a.getTime() === b.getTime() : false; + } + aValidType = isSymbol(a); + bValidType = isSymbol(b); + if (aValidType || bValidType) { + return a === b; + } + aValidType = isArray(a); + bValidType = isArray(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? looseCompareArrays(a, b) : false; + } + aValidType = isObject(a); + bValidType = isObject(b); + if (aValidType || bValidType) { + if (!aValidType || !bValidType) { + return false; + } + const aKeysCount = Object.keys(a).length; + const bKeysCount = Object.keys(b).length; + if (aKeysCount !== bKeysCount) { + return false; + } + for (const key in a) { + const aHasKey = a.hasOwnProperty(key); + const bHasKey = b.hasOwnProperty(key); + if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) { + return false; + } + } + } + return String(a) === String(b); +} +function looseIndexOf(arr, val) { + return arr.findIndex((item) => looseEqual(item, val)); +} +var isRef = (val) => { + return !!(val && val["__v_isRef"] === true); +}; +var toDisplayString = (val) => { + return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? isRef(val) ? toDisplayString(val.value) : JSON.stringify(val, replacer, 2) : String(val); +}; +var replacer = (_key, val) => { + if (isRef(val)) { + return replacer(_key, val.value); + } else if (isMap(val)) { + return { + [`Map(${val.size})`]: [...val.entries()].reduce( + (entries, [key, val2], i) => { + entries[stringifySymbol(key, i) + " =>"] = val2; + return entries; + }, + {} + ) + }; + } else if (isSet(val)) { + return { + [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v)) + }; + } else if (isSymbol(val)) { + return stringifySymbol(val); + } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { + return String(val); + } + return val; +}; +var stringifySymbol = (v, i = "") => { + var _a; + return ( + // Symbol.description in es2019+ so we need to cast here to pass + // the lib: es2016 check + isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v + ); +}; + +// node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js +function warn(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} +var activeEffectScope; +var EffectScope = class { + constructor(detached = false) { + this.detached = detached; + this._active = true; + this._on = 0; + this.effects = []; + this.cleanups = []; + this._isPaused = false; + this.parent = activeEffectScope; + if (!detached && activeEffectScope) { + this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( + this + ) - 1; + } + } + get active() { + return this._active; + } + pause() { + if (this._active) { + this._isPaused = true; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].pause(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].pause(); + } + } + } + /** + * Resumes the effect scope, including all child scopes and effects. + */ + resume() { + if (this._active) { + if (this._isPaused) { + this._isPaused = false; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].resume(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].resume(); + } + } + } + } + run(fn) { + if (this._active) { + const currentEffectScope = activeEffectScope; + try { + activeEffectScope = this; + return fn(); + } finally { + activeEffectScope = currentEffectScope; + } + } else if (true) { + warn(`cannot run an inactive effect scope.`); + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + on() { + if (++this._on === 1) { + this.prevScope = activeEffectScope; + activeEffectScope = this; + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + off() { + if (this._on > 0 && --this._on === 0) { + activeEffectScope = this.prevScope; + this.prevScope = void 0; + } + } + stop(fromParent) { + if (this._active) { + this._active = false; + let i, l; + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].stop(); + } + this.effects.length = 0; + for (i = 0, l = this.cleanups.length; i < l; i++) { + this.cleanups[i](); + } + this.cleanups.length = 0; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].stop(true); + } + this.scopes.length = 0; + } + if (!this.detached && this.parent && !fromParent) { + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.parent = void 0; + } + } +}; +function effectScope(detached) { + return new EffectScope(detached); +} +function getCurrentScope() { + return activeEffectScope; +} +function onScopeDispose(fn, failSilently = false) { + if (activeEffectScope) { + activeEffectScope.cleanups.push(fn); + } else if (!failSilently) { + warn( + `onScopeDispose() is called when there is no active effect scope to be associated with.` + ); + } +} +var activeSub; +var pausedQueueEffects = /* @__PURE__ */ new WeakSet(); +var ReactiveEffect = class { + constructor(fn) { + this.fn = fn; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 1 | 4; + this.next = void 0; + this.cleanup = void 0; + this.scheduler = void 0; + if (activeEffectScope && activeEffectScope.active) { + activeEffectScope.effects.push(this); + } + } + pause() { + this.flags |= 64; + } + resume() { + if (this.flags & 64) { + this.flags &= -65; + if (pausedQueueEffects.has(this)) { + pausedQueueEffects.delete(this); + this.trigger(); + } + } + } + /** + * @internal + */ + notify() { + if (this.flags & 2 && !(this.flags & 32)) { + return; + } + if (!(this.flags & 8)) { + batch(this); + } + } + run() { + if (!(this.flags & 1)) { + return this.fn(); + } + this.flags |= 2; + cleanupEffect(this); + prepareDeps(this); + const prevEffect = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = this; + shouldTrack = true; + try { + return this.fn(); + } finally { + if (activeSub !== this) { + warn( + "Active effect was not restored correctly - this is likely a Vue internal bug." + ); + } + cleanupDeps(this); + activeSub = prevEffect; + shouldTrack = prevShouldTrack; + this.flags &= -3; + } + } + stop() { + if (this.flags & 1) { + for (let link = this.deps; link; link = link.nextDep) { + removeSub(link); + } + this.deps = this.depsTail = void 0; + cleanupEffect(this); + this.onStop && this.onStop(); + this.flags &= -2; + } + } + trigger() { + if (this.flags & 64) { + pausedQueueEffects.add(this); + } else if (this.scheduler) { + this.scheduler(); + } else { + this.runIfDirty(); + } + } + /** + * @internal + */ + runIfDirty() { + if (isDirty(this)) { + this.run(); + } + } + get dirty() { + return isDirty(this); + } +}; +var batchDepth = 0; +var batchedSub; +var batchedComputed; +function batch(sub, isComputed = false) { + sub.flags |= 8; + if (isComputed) { + sub.next = batchedComputed; + batchedComputed = sub; + return; + } + sub.next = batchedSub; + batchedSub = sub; +} +function startBatch() { + batchDepth++; +} +function endBatch() { + if (--batchDepth > 0) { + return; + } + if (batchedComputed) { + let e = batchedComputed; + batchedComputed = void 0; + while (e) { + const next = e.next; + e.next = void 0; + e.flags &= -9; + e = next; + } + } + let error; + while (batchedSub) { + let e = batchedSub; + batchedSub = void 0; + while (e) { + const next = e.next; + e.next = void 0; + e.flags &= -9; + if (e.flags & 1) { + try { + ; + e.trigger(); + } catch (err) { + if (!error) error = err; + } + } + e = next; + } + } + if (error) throw error; +} +function prepareDeps(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + link.version = -1; + link.prevActiveLink = link.dep.activeLink; + link.dep.activeLink = link; + } +} +function cleanupDeps(sub) { + let head; + let tail = sub.depsTail; + let link = tail; + while (link) { + const prev = link.prevDep; + if (link.version === -1) { + if (link === tail) tail = prev; + removeSub(link); + removeDep(link); + } else { + head = link; + } + link.dep.activeLink = link.prevActiveLink; + link.prevActiveLink = void 0; + link = prev; + } + sub.deps = head; + sub.depsTail = tail; +} +function isDirty(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + if (link.dep.version !== link.version || link.dep.computed && (refreshComputed(link.dep.computed) || link.dep.version !== link.version)) { + return true; + } + } + if (sub._dirty) { + return true; + } + return false; +} +function refreshComputed(computed3) { + if (computed3.flags & 4 && !(computed3.flags & 16)) { + return; + } + computed3.flags &= -17; + if (computed3.globalVersion === globalVersion) { + return; + } + computed3.globalVersion = globalVersion; + if (!computed3.isSSR && computed3.flags & 128 && (!computed3.deps && !computed3._dirty || !isDirty(computed3))) { + return; + } + computed3.flags |= 2; + const dep = computed3.dep; + const prevSub = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = computed3; + shouldTrack = true; + try { + prepareDeps(computed3); + const value = computed3.fn(computed3._value); + if (dep.version === 0 || hasChanged(value, computed3._value)) { + computed3.flags |= 128; + computed3._value = value; + dep.version++; + } + } catch (err) { + dep.version++; + throw err; + } finally { + activeSub = prevSub; + shouldTrack = prevShouldTrack; + cleanupDeps(computed3); + computed3.flags &= -3; + } +} +function removeSub(link, soft = false) { + const { dep, prevSub, nextSub } = link; + if (prevSub) { + prevSub.nextSub = nextSub; + link.prevSub = void 0; + } + if (nextSub) { + nextSub.prevSub = prevSub; + link.nextSub = void 0; + } + if (dep.subsHead === link) { + dep.subsHead = nextSub; + } + if (dep.subs === link) { + dep.subs = prevSub; + if (!prevSub && dep.computed) { + dep.computed.flags &= -5; + for (let l = dep.computed.deps; l; l = l.nextDep) { + removeSub(l, true); + } + } + } + if (!soft && !--dep.sc && dep.map) { + dep.map.delete(dep.key); + } +} +function removeDep(link) { + const { prevDep, nextDep } = link; + if (prevDep) { + prevDep.nextDep = nextDep; + link.prevDep = void 0; + } + if (nextDep) { + nextDep.prevDep = prevDep; + link.nextDep = void 0; + } +} +function effect(fn, options) { + if (fn.effect instanceof ReactiveEffect) { + fn = fn.effect.fn; + } + const e = new ReactiveEffect(fn); + if (options) { + extend(e, options); + } + try { + e.run(); + } catch (err) { + e.stop(); + throw err; + } + const runner = e.run.bind(e); + runner.effect = e; + return runner; +} +function stop(runner) { + runner.effect.stop(); +} +var shouldTrack = true; +var trackStack = []; +function pauseTracking() { + trackStack.push(shouldTrack); + shouldTrack = false; +} +function resetTracking() { + const last = trackStack.pop(); + shouldTrack = last === void 0 ? true : last; +} +function cleanupEffect(e) { + const { cleanup } = e; + e.cleanup = void 0; + if (cleanup) { + const prevSub = activeSub; + activeSub = void 0; + try { + cleanup(); + } finally { + activeSub = prevSub; + } + } +} +var globalVersion = 0; +var Link = class { + constructor(sub, dep) { + this.sub = sub; + this.dep = dep; + this.version = dep.version; + this.nextDep = this.prevDep = this.nextSub = this.prevSub = this.prevActiveLink = void 0; + } +}; +var Dep = class { + // TODO isolatedDeclarations "__v_skip" + constructor(computed3) { + this.computed = computed3; + this.version = 0; + this.activeLink = void 0; + this.subs = void 0; + this.map = void 0; + this.key = void 0; + this.sc = 0; + this.__v_skip = true; + if (true) { + this.subsHead = void 0; + } + } + track(debugInfo) { + if (!activeSub || !shouldTrack || activeSub === this.computed) { + return; + } + let link = this.activeLink; + if (link === void 0 || link.sub !== activeSub) { + link = this.activeLink = new Link(activeSub, this); + if (!activeSub.deps) { + activeSub.deps = activeSub.depsTail = link; + } else { + link.prevDep = activeSub.depsTail; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + } + addSub(link); + } else if (link.version === -1) { + link.version = this.version; + if (link.nextDep) { + const next = link.nextDep; + next.prevDep = link.prevDep; + if (link.prevDep) { + link.prevDep.nextDep = next; + } + link.prevDep = activeSub.depsTail; + link.nextDep = void 0; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + if (activeSub.deps === link) { + activeSub.deps = next; + } + } + } + if (activeSub.onTrack) { + activeSub.onTrack( + extend( + { + effect: activeSub + }, + debugInfo + ) + ); + } + return link; + } + trigger(debugInfo) { + this.version++; + globalVersion++; + this.notify(debugInfo); + } + notify(debugInfo) { + startBatch(); + try { + if (true) { + for (let head = this.subsHead; head; head = head.nextSub) { + if (head.sub.onTrigger && !(head.sub.flags & 8)) { + head.sub.onTrigger( + extend( + { + effect: head.sub + }, + debugInfo + ) + ); + } + } + } + for (let link = this.subs; link; link = link.prevSub) { + if (link.sub.notify()) { + ; + link.sub.dep.notify(); + } + } + } finally { + endBatch(); + } + } +}; +function addSub(link) { + link.dep.sc++; + if (link.sub.flags & 4) { + const computed3 = link.dep.computed; + if (computed3 && !link.dep.subs) { + computed3.flags |= 4 | 16; + for (let l = computed3.deps; l; l = l.nextDep) { + addSub(l); + } + } + const currentTail = link.dep.subs; + if (currentTail !== link) { + link.prevSub = currentTail; + if (currentTail) currentTail.nextSub = link; + } + if (link.dep.subsHead === void 0) { + link.dep.subsHead = link; + } + link.dep.subs = link; + } +} +var targetMap = /* @__PURE__ */ new WeakMap(); +var ITERATE_KEY = Symbol( + true ? "Object iterate" : "" +); +var MAP_KEY_ITERATE_KEY = Symbol( + true ? "Map keys iterate" : "" +); +var ARRAY_ITERATE_KEY = Symbol( + true ? "Array iterate" : "" +); +function track(target, type, key) { + if (shouldTrack && activeSub) { + let depsMap = targetMap.get(target); + if (!depsMap) { + targetMap.set(target, depsMap = /* @__PURE__ */ new Map()); + } + let dep = depsMap.get(key); + if (!dep) { + depsMap.set(key, dep = new Dep()); + dep.map = depsMap; + dep.key = key; + } + if (true) { + dep.track({ + target, + type, + key + }); + } else { + dep.track(); + } + } +} +function trigger(target, type, key, newValue, oldValue, oldTarget) { + const depsMap = targetMap.get(target); + if (!depsMap) { + globalVersion++; + return; + } + const run = (dep) => { + if (dep) { + if (true) { + dep.trigger({ + target, + type, + key, + newValue, + oldValue, + oldTarget + }); + } else { + dep.trigger(); + } + } + }; + startBatch(); + if (type === "clear") { + depsMap.forEach(run); + } else { + const targetIsArray = isArray(target); + const isArrayIndex = targetIsArray && isIntegerKey(key); + if (targetIsArray && key === "length") { + const newLength = Number(newValue); + depsMap.forEach((dep, key2) => { + if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) { + run(dep); + } + }); + } else { + if (key !== void 0 || depsMap.has(void 0)) { + run(depsMap.get(key)); + } + if (isArrayIndex) { + run(depsMap.get(ARRAY_ITERATE_KEY)); + } + switch (type) { + case "add": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } else if (isArrayIndex) { + run(depsMap.get("length")); + } + break; + case "delete": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } + break; + case "set": + if (isMap(target)) { + run(depsMap.get(ITERATE_KEY)); + } + break; + } + } + } + endBatch(); +} +function getDepFromReactive(object, key) { + const depMap = targetMap.get(object); + return depMap && depMap.get(key); +} +function reactiveReadArray(array) { + const raw = toRaw(array); + if (raw === array) return raw; + track(raw, "iterate", ARRAY_ITERATE_KEY); + return isShallow(array) ? raw : raw.map(toReactive); +} +function shallowReadArray(arr) { + track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY); + return arr; +} +var arrayInstrumentations = { + __proto__: null, + [Symbol.iterator]() { + return iterator(this, Symbol.iterator, toReactive); + }, + concat(...args) { + return reactiveReadArray(this).concat( + ...args.map((x) => isArray(x) ? reactiveReadArray(x) : x) + ); + }, + entries() { + return iterator(this, "entries", (value) => { + value[1] = toReactive(value[1]); + return value; + }); + }, + every(fn, thisArg) { + return apply(this, "every", fn, thisArg, void 0, arguments); + }, + filter(fn, thisArg) { + return apply(this, "filter", fn, thisArg, (v) => v.map(toReactive), arguments); + }, + find(fn, thisArg) { + return apply(this, "find", fn, thisArg, toReactive, arguments); + }, + findIndex(fn, thisArg) { + return apply(this, "findIndex", fn, thisArg, void 0, arguments); + }, + findLast(fn, thisArg) { + return apply(this, "findLast", fn, thisArg, toReactive, arguments); + }, + findLastIndex(fn, thisArg) { + return apply(this, "findLastIndex", fn, thisArg, void 0, arguments); + }, + // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement + forEach(fn, thisArg) { + return apply(this, "forEach", fn, thisArg, void 0, arguments); + }, + includes(...args) { + return searchProxy(this, "includes", args); + }, + indexOf(...args) { + return searchProxy(this, "indexOf", args); + }, + join(separator) { + return reactiveReadArray(this).join(separator); + }, + // keys() iterator only reads `length`, no optimisation required + lastIndexOf(...args) { + return searchProxy(this, "lastIndexOf", args); + }, + map(fn, thisArg) { + return apply(this, "map", fn, thisArg, void 0, arguments); + }, + pop() { + return noTracking(this, "pop"); + }, + push(...args) { + return noTracking(this, "push", args); + }, + reduce(fn, ...args) { + return reduce(this, "reduce", fn, args); + }, + reduceRight(fn, ...args) { + return reduce(this, "reduceRight", fn, args); + }, + shift() { + return noTracking(this, "shift"); + }, + // slice could use ARRAY_ITERATE but also seems to beg for range tracking + some(fn, thisArg) { + return apply(this, "some", fn, thisArg, void 0, arguments); + }, + splice(...args) { + return noTracking(this, "splice", args); + }, + toReversed() { + return reactiveReadArray(this).toReversed(); + }, + toSorted(comparer) { + return reactiveReadArray(this).toSorted(comparer); + }, + toSpliced(...args) { + return reactiveReadArray(this).toSpliced(...args); + }, + unshift(...args) { + return noTracking(this, "unshift", args); + }, + values() { + return iterator(this, "values", toReactive); + } +}; +function iterator(self2, method, wrapValue) { + const arr = shallowReadArray(self2); + const iter = arr[method](); + if (arr !== self2 && !isShallow(self2)) { + iter._next = iter.next; + iter.next = () => { + const result = iter._next(); + if (result.value) { + result.value = wrapValue(result.value); + } + return result; + }; + } + return iter; +} +var arrayProto = Array.prototype; +function apply(self2, method, fn, thisArg, wrappedRetFn, args) { + const arr = shallowReadArray(self2); + const needsWrap = arr !== self2 && !isShallow(self2); + const methodFn = arr[method]; + if (methodFn !== arrayProto[method]) { + const result2 = methodFn.apply(self2, args); + return needsWrap ? toReactive(result2) : result2; + } + let wrappedFn = fn; + if (arr !== self2) { + if (needsWrap) { + wrappedFn = function(item, index) { + return fn.call(this, toReactive(item), index, self2); + }; + } else if (fn.length > 2) { + wrappedFn = function(item, index) { + return fn.call(this, item, index, self2); + }; + } + } + const result = methodFn.call(arr, wrappedFn, thisArg); + return needsWrap && wrappedRetFn ? wrappedRetFn(result) : result; +} +function reduce(self2, method, fn, args) { + const arr = shallowReadArray(self2); + let wrappedFn = fn; + if (arr !== self2) { + if (!isShallow(self2)) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, toReactive(item), index, self2); + }; + } else if (fn.length > 3) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, item, index, self2); + }; + } + } + return arr[method](wrappedFn, ...args); +} +function searchProxy(self2, method, args) { + const arr = toRaw(self2); + track(arr, "iterate", ARRAY_ITERATE_KEY); + const res = arr[method](...args); + if ((res === -1 || res === false) && isProxy(args[0])) { + args[0] = toRaw(args[0]); + return arr[method](...args); + } + return res; +} +function noTracking(self2, method, args = []) { + pauseTracking(); + startBatch(); + const res = toRaw(self2)[method].apply(self2, args); + endBatch(); + resetTracking(); + return res; +} +var isNonTrackableKeys = makeMap(`__proto__,__v_isRef,__isVue`); +var builtInSymbols = new Set( + Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol) +); +function hasOwnProperty2(key) { + if (!isSymbol(key)) key = String(key); + const obj = toRaw(this); + track(obj, "has", key); + return obj.hasOwnProperty(key); +} +var BaseReactiveHandler = class { + constructor(_isReadonly = false, _isShallow = false) { + this._isReadonly = _isReadonly; + this._isShallow = _isShallow; + } + get(target, key, receiver) { + if (key === "__v_skip") return target["__v_skip"]; + const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow; + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_isShallow") { + return isShallow2; + } else if (key === "__v_raw") { + if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype + // this means the receiver is a user proxy of the reactive proxy + Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) { + return target; + } + return; + } + const targetIsArray = isArray(target); + if (!isReadonly2) { + let fn; + if (targetIsArray && (fn = arrayInstrumentations[key])) { + return fn; + } + if (key === "hasOwnProperty") { + return hasOwnProperty2; + } + } + const res = Reflect.get( + target, + key, + // if this is a proxy wrapping a ref, return methods using the raw ref + // as receiver so that we don't have to call `toRaw` on the ref in all + // its class methods + isRef2(target) ? target : receiver + ); + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { + return res; + } + if (!isReadonly2) { + track(target, "get", key); + } + if (isShallow2) { + return res; + } + if (isRef2(res)) { + return targetIsArray && isIntegerKey(key) ? res : res.value; + } + if (isObject(res)) { + return isReadonly2 ? readonly(res) : reactive(res); + } + return res; + } +}; +var MutableReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { + let oldValue = target[key]; + if (!this._isShallow) { + const isOldValueReadonly = isReadonly(oldValue); + if (!isShallow(value) && !isReadonly(value)) { + oldValue = toRaw(oldValue); + value = toRaw(value); + } + if (!isArray(target) && isRef2(oldValue) && !isRef2(value)) { + if (isOldValueReadonly) { + return false; + } else { + oldValue.value = value; + return true; + } + } + } + const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key); + const result = Reflect.set( + target, + key, + value, + isRef2(target) ? target : receiver + ); + if (target === toRaw(receiver)) { + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + } + return result; + } + deleteProperty(target, key) { + const hadKey = hasOwn(target, key); + const oldValue = target[key]; + const result = Reflect.deleteProperty(target, key); + if (result && hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + } + has(target, key) { + const result = Reflect.has(target, key); + if (!isSymbol(key) || !builtInSymbols.has(key)) { + track(target, "has", key); + } + return result; + } + ownKeys(target) { + track( + target, + "iterate", + isArray(target) ? "length" : ITERATE_KEY + ); + return Reflect.ownKeys(target); + } +}; +var ReadonlyReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } + set(target, key) { + if (true) { + warn( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } + deleteProperty(target, key) { + if (true) { + warn( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } +}; +var mutableHandlers = new MutableReactiveHandler(); +var readonlyHandlers = new ReadonlyReactiveHandler(); +var shallowReactiveHandlers = new MutableReactiveHandler(true); +var shallowReadonlyHandlers = new ReadonlyReactiveHandler(true); +var toShallow = (value) => value; +var getProto = (v) => Reflect.getPrototypeOf(v); +function createIterableMethod(method, isReadonly2, isShallow2) { + return function(...args) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const targetIsMap = isMap(rawTarget); + const isPair = method === "entries" || method === Symbol.iterator && targetIsMap; + const isKeyOnly = method === "keys" && targetIsMap; + const innerIterator = target[method](...args); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track( + rawTarget, + "iterate", + isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY + ); + return { + // iterator protocol + next() { + const { value, done } = innerIterator.next(); + return done ? { value, done } : { + value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), + done + }; + }, + // iterable protocol + [Symbol.iterator]() { + return this; + } + }; + }; +} +function createReadonlyMethod(type) { + return function(...args) { + if (true) { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } + return type === "delete" ? false : type === "clear" ? void 0 : this; + }; +} +function createInstrumentations(readonly2, shallow) { + const instrumentations = { + get(key) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!readonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "get", key); + } + track(rawTarget, "get", rawKey); + } + const { has } = getProto(rawTarget); + const wrap = shallow ? toShallow : readonly2 ? toReadonly : toReactive; + if (has.call(rawTarget, key)) { + return wrap(target.get(key)); + } else if (has.call(rawTarget, rawKey)) { + return wrap(target.get(rawKey)); + } else if (target !== rawTarget) { + target.get(key); + } + }, + get size() { + const target = this["__v_raw"]; + !readonly2 && track(toRaw(target), "iterate", ITERATE_KEY); + return Reflect.get(target, "size", target); + }, + has(key) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!readonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "has", key); + } + track(rawTarget, "has", rawKey); + } + return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey); + }, + forEach(callback, thisArg) { + const observed = this; + const target = observed["__v_raw"]; + const rawTarget = toRaw(target); + const wrap = shallow ? toShallow : readonly2 ? toReadonly : toReactive; + !readonly2 && track(rawTarget, "iterate", ITERATE_KEY); + return target.forEach((value, key) => { + return callback.call(thisArg, wrap(value), wrap(key), observed); + }); + } + }; + extend( + instrumentations, + readonly2 ? { + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear") + } : { + add(value) { + if (!shallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const proto = getProto(target); + const hadKey = proto.has.call(target, value); + if (!hadKey) { + target.add(value); + trigger(target, "add", value, value); + } + return this; + }, + set(key, value) { + if (!shallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const { has, get } = getProto(target); + let hadKey = has.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has.call(target, key); + } else if (true) { + checkIdentityKeys(target, has, key); + } + const oldValue = get.call(target, key); + target.set(key, value); + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + return this; + }, + delete(key) { + const target = toRaw(this); + const { has, get } = getProto(target); + let hadKey = has.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has.call(target, key); + } else if (true) { + checkIdentityKeys(target, has, key); + } + const oldValue = get ? get.call(target, key) : void 0; + const result = target.delete(key); + if (hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + }, + clear() { + const target = toRaw(this); + const hadItems = target.size !== 0; + const oldTarget = true ? isMap(target) ? new Map(target) : new Set(target) : void 0; + const result = target.clear(); + if (hadItems) { + trigger( + target, + "clear", + void 0, + void 0, + oldTarget + ); + } + return result; + } + } + ); + const iteratorMethods = [ + "keys", + "values", + "entries", + Symbol.iterator + ]; + iteratorMethods.forEach((method) => { + instrumentations[method] = createIterableMethod(method, readonly2, shallow); + }); + return instrumentations; +} +function createInstrumentationGetter(isReadonly2, shallow) { + const instrumentations = createInstrumentations(isReadonly2, shallow); + return (target, key, receiver) => { + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_raw") { + return target; + } + return Reflect.get( + hasOwn(instrumentations, key) && key in target ? instrumentations : target, + key, + receiver + ); + }; +} +var mutableCollectionHandlers = { + get: createInstrumentationGetter(false, false) +}; +var shallowCollectionHandlers = { + get: createInstrumentationGetter(false, true) +}; +var readonlyCollectionHandlers = { + get: createInstrumentationGetter(true, false) +}; +var shallowReadonlyCollectionHandlers = { + get: createInstrumentationGetter(true, true) +}; +function checkIdentityKeys(target, has, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has.call(target, rawKey)) { + const type = toRawType(target); + warn( + `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` + ); + } +} +var reactiveMap = /* @__PURE__ */ new WeakMap(); +var shallowReactiveMap = /* @__PURE__ */ new WeakMap(); +var readonlyMap = /* @__PURE__ */ new WeakMap(); +var shallowReadonlyMap = /* @__PURE__ */ new WeakMap(); +function targetTypeMap(rawType) { + switch (rawType) { + case "Object": + case "Array": + return 1; + case "Map": + case "Set": + case "WeakMap": + case "WeakSet": + return 2; + default: + return 0; + } +} +function getTargetType(value) { + return value["__v_skip"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value)); +} +function reactive(target) { + if (isReadonly(target)) { + return target; + } + return createReactiveObject( + target, + false, + mutableHandlers, + mutableCollectionHandlers, + reactiveMap + ); +} +function shallowReactive(target) { + return createReactiveObject( + target, + false, + shallowReactiveHandlers, + shallowCollectionHandlers, + shallowReactiveMap + ); +} +function readonly(target) { + return createReactiveObject( + target, + true, + readonlyHandlers, + readonlyCollectionHandlers, + readonlyMap + ); +} +function shallowReadonly(target) { + return createReactiveObject( + target, + true, + shallowReadonlyHandlers, + shallowReadonlyCollectionHandlers, + shallowReadonlyMap + ); +} +function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { + if (!isObject(target)) { + if (true) { + warn( + `value cannot be made ${isReadonly2 ? "readonly" : "reactive"}: ${String( + target + )}` + ); + } + return target; + } + if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { + return target; + } + const targetType = getTargetType(target); + if (targetType === 0) { + return target; + } + const existingProxy = proxyMap.get(target); + if (existingProxy) { + return existingProxy; + } + const proxy = new Proxy( + target, + targetType === 2 ? collectionHandlers : baseHandlers + ); + proxyMap.set(target, proxy); + return proxy; +} +function isReactive(value) { + if (isReadonly(value)) { + return isReactive(value["__v_raw"]); + } + return !!(value && value["__v_isReactive"]); +} +function isReadonly(value) { + return !!(value && value["__v_isReadonly"]); +} +function isShallow(value) { + return !!(value && value["__v_isShallow"]); +} +function isProxy(value) { + return value ? !!value["__v_raw"] : false; +} +function toRaw(observed) { + const raw = observed && observed["__v_raw"]; + return raw ? toRaw(raw) : observed; +} +function markRaw(value) { + if (!hasOwn(value, "__v_skip") && Object.isExtensible(value)) { + def(value, "__v_skip", true); + } + return value; +} +var toReactive = (value) => isObject(value) ? reactive(value) : value; +var toReadonly = (value) => isObject(value) ? readonly(value) : value; +function isRef2(r) { + return r ? r["__v_isRef"] === true : false; +} +function ref(value) { + return createRef(value, false); +} +function shallowRef(value) { + return createRef(value, true); +} +function createRef(rawValue, shallow) { + if (isRef2(rawValue)) { + return rawValue; + } + return new RefImpl(rawValue, shallow); +} +var RefImpl = class { + constructor(value, isShallow2) { + this.dep = new Dep(); + this["__v_isRef"] = true; + this["__v_isShallow"] = false; + this._rawValue = isShallow2 ? value : toRaw(value); + this._value = isShallow2 ? value : toReactive(value); + this["__v_isShallow"] = isShallow2; + } + get value() { + if (true) { + this.dep.track({ + target: this, + type: "get", + key: "value" + }); + } else { + this.dep.track(); + } + return this._value; + } + set value(newValue) { + const oldValue = this._rawValue; + const useDirectValue = this["__v_isShallow"] || isShallow(newValue) || isReadonly(newValue); + newValue = useDirectValue ? newValue : toRaw(newValue); + if (hasChanged(newValue, oldValue)) { + this._rawValue = newValue; + this._value = useDirectValue ? newValue : toReactive(newValue); + if (true) { + this.dep.trigger({ + target: this, + type: "set", + key: "value", + newValue, + oldValue + }); + } else { + this.dep.trigger(); + } + } + } +}; +function triggerRef(ref2) { + if (ref2.dep) { + if (true) { + ref2.dep.trigger({ + target: ref2, + type: "set", + key: "value", + newValue: ref2._value + }); + } else { + ref2.dep.trigger(); + } + } +} +function unref(ref2) { + return isRef2(ref2) ? ref2.value : ref2; +} +function toValue(source) { + return isFunction(source) ? source() : unref(source); +} +var shallowUnwrapHandlers = { + get: (target, key, receiver) => key === "__v_raw" ? target : unref(Reflect.get(target, key, receiver)), + set: (target, key, value, receiver) => { + const oldValue = target[key]; + if (isRef2(oldValue) && !isRef2(value)) { + oldValue.value = value; + return true; + } else { + return Reflect.set(target, key, value, receiver); + } + } +}; +function proxyRefs(objectWithRefs) { + return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers); +} +var CustomRefImpl = class { + constructor(factory) { + this["__v_isRef"] = true; + this._value = void 0; + const dep = this.dep = new Dep(); + const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep)); + this._get = get; + this._set = set; + } + get value() { + return this._value = this._get(); + } + set value(newVal) { + this._set(newVal); + } +}; +function customRef(factory) { + return new CustomRefImpl(factory); +} +function toRefs(object) { + if (!isProxy(object)) { + warn(`toRefs() expects a reactive object but received a plain one.`); + } + const ret = isArray(object) ? new Array(object.length) : {}; + for (const key in object) { + ret[key] = propertyToRef(object, key); + } + return ret; +} +var ObjectRefImpl = class { + constructor(_object, _key, _defaultValue) { + this._object = _object; + this._key = _key; + this._defaultValue = _defaultValue; + this["__v_isRef"] = true; + this._value = void 0; + } + get value() { + const val = this._object[this._key]; + return this._value = val === void 0 ? this._defaultValue : val; + } + set value(newVal) { + this._object[this._key] = newVal; + } + get dep() { + return getDepFromReactive(toRaw(this._object), this._key); + } +}; +var GetterRefImpl = class { + constructor(_getter) { + this._getter = _getter; + this["__v_isRef"] = true; + this["__v_isReadonly"] = true; + this._value = void 0; + } + get value() { + return this._value = this._getter(); + } +}; +function toRef(source, key, defaultValue) { + if (isRef2(source)) { + return source; + } else if (isFunction(source)) { + return new GetterRefImpl(source); + } else if (isObject(source) && arguments.length > 1) { + return propertyToRef(source, key, defaultValue); + } else { + return ref(source); + } +} +function propertyToRef(source, key, defaultValue) { + const val = source[key]; + return isRef2(val) ? val : new ObjectRefImpl(source, key, defaultValue); +} +var ComputedRefImpl = class { + constructor(fn, setter, isSSR) { + this.fn = fn; + this.setter = setter; + this._value = void 0; + this.dep = new Dep(this); + this.__v_isRef = true; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 16; + this.globalVersion = globalVersion - 1; + this.next = void 0; + this.effect = this; + this["__v_isReadonly"] = !setter; + this.isSSR = isSSR; + } + /** + * @internal + */ + notify() { + this.flags |= 16; + if (!(this.flags & 8) && // avoid infinite self recursion + activeSub !== this) { + batch(this, true); + return true; + } else if (true) ; + } + get value() { + const link = true ? this.dep.track({ + target: this, + type: "get", + key: "value" + }) : this.dep.track(); + refreshComputed(this); + if (link) { + link.version = this.dep.version; + } + return this._value; + } + set value(newValue) { + if (this.setter) { + this.setter(newValue); + } else if (true) { + warn("Write operation failed: computed value is readonly"); + } + } +}; +function computed(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + if (isFunction(getterOrOptions)) { + getter = getterOrOptions; + } else { + getter = getterOrOptions.get; + setter = getterOrOptions.set; + } + const cRef = new ComputedRefImpl(getter, setter, isSSR); + if (debugOptions && !isSSR) { + cRef.onTrack = debugOptions.onTrack; + cRef.onTrigger = debugOptions.onTrigger; + } + return cRef; +} +var TrackOpTypes = { + "GET": "get", + "HAS": "has", + "ITERATE": "iterate" +}; +var TriggerOpTypes = { + "SET": "set", + "ADD": "add", + "DELETE": "delete", + "CLEAR": "clear" +}; +var INITIAL_WATCHER_VALUE = {}; +var cleanupMap = /* @__PURE__ */ new WeakMap(); +var activeWatcher = void 0; +function getCurrentWatcher() { + return activeWatcher; +} +function onWatcherCleanup(cleanupFn, failSilently = false, owner = activeWatcher) { + if (owner) { + let cleanups = cleanupMap.get(owner); + if (!cleanups) cleanupMap.set(owner, cleanups = []); + cleanups.push(cleanupFn); + } else if (!failSilently) { + warn( + `onWatcherCleanup() was called when there was no active watcher to associate with.` + ); + } +} +function watch(source, cb, options = EMPTY_OBJ) { + const { immediate, deep, once, scheduler, augmentJob, call } = options; + const warnInvalidSource = (s) => { + (options.onWarn || warn)( + `Invalid watch source: `, + s, + `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` + ); + }; + const reactiveGetter = (source2) => { + if (deep) return source2; + if (isShallow(source2) || deep === false || deep === 0) + return traverse(source2, 1); + return traverse(source2); + }; + let effect2; + let getter; + let cleanup; + let boundCleanup; + let forceTrigger = false; + let isMultiSource = false; + if (isRef2(source)) { + getter = () => source.value; + forceTrigger = isShallow(source); + } else if (isReactive(source)) { + getter = () => reactiveGetter(source); + forceTrigger = true; + } else if (isArray(source)) { + isMultiSource = true; + forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); + getter = () => source.map((s) => { + if (isRef2(s)) { + return s.value; + } else if (isReactive(s)) { + return reactiveGetter(s); + } else if (isFunction(s)) { + return call ? call(s, 2) : s(); + } else { + warnInvalidSource(s); + } + }); + } else if (isFunction(source)) { + if (cb) { + getter = call ? () => call(source, 2) : source; + } else { + getter = () => { + if (cleanup) { + pauseTracking(); + try { + cleanup(); + } finally { + resetTracking(); + } + } + const currentEffect = activeWatcher; + activeWatcher = effect2; + try { + return call ? call(source, 3, [boundCleanup]) : source(boundCleanup); + } finally { + activeWatcher = currentEffect; + } + }; + } + } else { + getter = NOOP; + warnInvalidSource(source); + } + if (cb && deep) { + const baseGetter = getter; + const depth = deep === true ? Infinity : deep; + getter = () => traverse(baseGetter(), depth); + } + const scope = getCurrentScope(); + const watchHandle = () => { + effect2.stop(); + if (scope && scope.active) { + remove(scope.effects, effect2); + } + }; + if (once && cb) { + const _cb = cb; + cb = (...args) => { + _cb(...args); + watchHandle(); + }; + } + let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; + const job = (immediateFirstRun) => { + if (!(effect2.flags & 1) || !effect2.dirty && !immediateFirstRun) { + return; + } + if (cb) { + const newValue = effect2.run(); + if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue))) { + if (cleanup) { + cleanup(); + } + const currentWatcher = activeWatcher; + activeWatcher = effect2; + try { + const args = [ + newValue, + // pass undefined as the old value when it's changed for the first time + oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue, + boundCleanup + ]; + oldValue = newValue; + call ? call(cb, 3, args) : ( + // @ts-expect-error + cb(...args) + ); + } finally { + activeWatcher = currentWatcher; + } + } + } else { + effect2.run(); + } + }; + if (augmentJob) { + augmentJob(job); + } + effect2 = new ReactiveEffect(getter); + effect2.scheduler = scheduler ? () => scheduler(job, false) : job; + boundCleanup = (fn) => onWatcherCleanup(fn, false, effect2); + cleanup = effect2.onStop = () => { + const cleanups = cleanupMap.get(effect2); + if (cleanups) { + if (call) { + call(cleanups, 4); + } else { + for (const cleanup2 of cleanups) cleanup2(); + } + cleanupMap.delete(effect2); + } + }; + if (true) { + effect2.onTrack = options.onTrack; + effect2.onTrigger = options.onTrigger; + } + if (cb) { + if (immediate) { + job(true); + } else { + oldValue = effect2.run(); + } + } else if (scheduler) { + scheduler(job.bind(null, true), true); + } else { + effect2.run(); + } + watchHandle.pause = effect2.pause.bind(effect2); + watchHandle.resume = effect2.resume.bind(effect2); + watchHandle.stop = watchHandle; + return watchHandle; +} +function traverse(value, depth = Infinity, seen) { + if (depth <= 0 || !isObject(value) || value["__v_skip"]) { + return value; + } + seen = seen || /* @__PURE__ */ new Set(); + if (seen.has(value)) { + return value; + } + seen.add(value); + depth--; + if (isRef2(value)) { + traverse(value.value, depth, seen); + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + traverse(value[i], depth, seen); + } + } else if (isSet(value) || isMap(value)) { + value.forEach((v) => { + traverse(v, depth, seen); + }); + } else if (isPlainObject(value)) { + for (const key in value) { + traverse(value[key], depth, seen); + } + for (const key of Object.getOwnPropertySymbols(value)) { + if (Object.prototype.propertyIsEnumerable.call(value, key)) { + traverse(value[key], depth, seen); + } + } + } + return value; +} + +// node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +var stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} +var isWarning = false; +function warn$1(msg, ...args) { + if (isWarning) return; + isWarning = true; + pauseTracking(); + const instance = stack.length ? stack[stack.length - 1].component : null; + const appWarnHandler = instance && instance.appContext.config.warnHandler; + const trace = getComponentTrace(); + if (appWarnHandler) { + callWithErrorHandling( + appWarnHandler, + instance, + 11, + [ + // eslint-disable-next-line no-restricted-syntax + msg + args.map((a) => { + var _a, _b; + return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a); + }).join(""), + instance && instance.proxy, + trace.map( + ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>` + ).join("\n"), + trace + ] + ); + } else { + const warnArgs = [`[Vue warn]: ${msg}`, ...args]; + if (trace.length && // avoid spamming console during tests + true) { + warnArgs.push(` +`, ...formatTrace(trace)); + } + console.warn(...warnArgs); + } + resetTracking(); + isWarning = false; +} +function getComponentTrace() { + let currentVNode = stack[stack.length - 1]; + if (!currentVNode) { + return []; + } + const normalizedStack = []; + while (currentVNode) { + const last = normalizedStack[0]; + if (last && last.vnode === currentVNode) { + last.recurseCount++; + } else { + normalizedStack.push({ + vnode: currentVNode, + recurseCount: 0 + }); + } + const parentInstance = currentVNode.component && currentVNode.component.parent; + currentVNode = parentInstance && parentInstance.vnode; + } + return normalizedStack; +} +function formatTrace(trace) { + const logs = []; + trace.forEach((entry, i) => { + logs.push(...i === 0 ? [] : [` +`], ...formatTraceEntry(entry)); + }); + return logs; +} +function formatTraceEntry({ vnode, recurseCount }) { + const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; + const isRoot = vnode.component ? vnode.component.parent == null : false; + const open = ` at <${formatComponentName( + vnode.component, + vnode.type, + isRoot + )}`; + const close = `>` + postfix; + return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close]; +} +function formatProps(props) { + const res = []; + const keys = Object.keys(props); + keys.slice(0, 3).forEach((key) => { + res.push(...formatProp(key, props[key])); + }); + if (keys.length > 3) { + res.push(` ...`); + } + return res; +} +function formatProp(key, value, raw) { + if (isString(value)) { + value = JSON.stringify(value); + return raw ? value : [`${key}=${value}`]; + } else if (typeof value === "number" || typeof value === "boolean" || value == null) { + return raw ? value : [`${key}=${value}`]; + } else if (isRef2(value)) { + value = formatProp(key, toRaw(value.value), true); + return raw ? value : [`${key}=Ref<`, value, `>`]; + } else if (isFunction(value)) { + return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + } else { + value = toRaw(value); + return raw ? value : [`${key}=`, value]; + } +} +function assertNumber(val, type) { + if (false) return; + if (val === void 0) { + return; + } else if (typeof val !== "number") { + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + } else if (isNaN(val)) { + warn$1(`${type} is NaN - the duration expression might be incorrect.`); + } +} +var ErrorCodes = { + "SETUP_FUNCTION": 0, + "0": "SETUP_FUNCTION", + "RENDER_FUNCTION": 1, + "1": "RENDER_FUNCTION", + "NATIVE_EVENT_HANDLER": 5, + "5": "NATIVE_EVENT_HANDLER", + "COMPONENT_EVENT_HANDLER": 6, + "6": "COMPONENT_EVENT_HANDLER", + "VNODE_HOOK": 7, + "7": "VNODE_HOOK", + "DIRECTIVE_HOOK": 8, + "8": "DIRECTIVE_HOOK", + "TRANSITION_HOOK": 9, + "9": "TRANSITION_HOOK", + "APP_ERROR_HANDLER": 10, + "10": "APP_ERROR_HANDLER", + "APP_WARN_HANDLER": 11, + "11": "APP_WARN_HANDLER", + "FUNCTION_REF": 12, + "12": "FUNCTION_REF", + "ASYNC_COMPONENT_LOADER": 13, + "13": "ASYNC_COMPONENT_LOADER", + "SCHEDULER": 14, + "14": "SCHEDULER", + "COMPONENT_UPDATE": 15, + "15": "COMPONENT_UPDATE", + "APP_UNMOUNT_CLEANUP": 16, + "16": "APP_UNMOUNT_CLEANUP" +}; +var ErrorTypeStrings$1 = { + ["sp"]: "serverPrefetch hook", + ["bc"]: "beforeCreate hook", + ["c"]: "created hook", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [11]: "app warnHandler", + [12]: "ref function", + [13]: "async component loader", + [14]: "scheduler flush", + [15]: "component update", + [16]: "app unmount cleanup function" +}; +function callWithErrorHandling(fn, instance, type, args) { + try { + return args ? fn(...args) : fn(); + } catch (err) { + handleError(err, instance, type); + } +} +function callWithAsyncErrorHandling(fn, instance, type, args) { + if (isFunction(fn)) { + const res = callWithErrorHandling(fn, instance, type, args); + if (res && isPromise(res)) { + res.catch((err) => { + handleError(err, instance, type); + }); + } + return res; + } + if (isArray(fn)) { + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + return values; + } else if (true) { + warn$1( + `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}` + ); + } +} +function handleError(err, instance, type, throwInDev = true) { + const contextVNode = instance ? instance.vnode : null; + const { errorHandler, throwUnhandledErrorInProduction } = instance && instance.appContext.config || EMPTY_OBJ; + if (instance) { + let cur = instance.parent; + const exposedInstance = instance.proxy; + const errorInfo = true ? ErrorTypeStrings$1[type] : `https://vuejs.org/error-reference/#runtime-${type}`; + while (cur) { + const errorCapturedHooks = cur.ec; + if (errorCapturedHooks) { + for (let i = 0; i < errorCapturedHooks.length; i++) { + if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { + return; + } + } + } + cur = cur.parent; + } + if (errorHandler) { + pauseTracking(); + callWithErrorHandling(errorHandler, null, 10, [ + err, + exposedInstance, + errorInfo + ]); + resetTracking(); + return; + } + } + logError(err, type, contextVNode, throwInDev, throwUnhandledErrorInProduction); +} +function logError(err, type, contextVNode, throwInDev = true, throwInProd = false) { + if (true) { + const info = ErrorTypeStrings$1[type]; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + throw err; + } else { + console.error(err); + } + } else if (throwInProd) { + throw err; + } else { + console.error(err); + } +} +var queue = []; +var flushIndex = -1; +var pendingPostFlushCbs = []; +var activePostFlushCbs = null; +var postFlushIndex = 0; +var resolvedPromise = Promise.resolve(); +var currentFlushPromise = null; +var RECURSION_LIMIT = 100; +function nextTick(fn) { + const p2 = currentFlushPromise || resolvedPromise; + return fn ? p2.then(this ? fn.bind(this) : fn) : p2; +} +function findInsertionIndex(id) { + let start = flushIndex + 1; + let end = queue.length; + while (start < end) { + const middle = start + end >>> 1; + const middleJob = queue[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.flags & 2) { + start = middle + 1; + } else { + end = middle; + } + } + return start; +} +function queueJob(job) { + if (!(job.flags & 1)) { + const jobId = getId(job); + const lastJob = queue[queue.length - 1]; + if (!lastJob || // fast path when the job id is larger than the tail + !(job.flags & 2) && jobId >= getId(lastJob)) { + queue.push(job); + } else { + queue.splice(findInsertionIndex(jobId), 0, job); + } + job.flags |= 1; + queueFlush(); + } +} +function queueFlush() { + if (!currentFlushPromise) { + currentFlushPromise = resolvedPromise.then(flushJobs); + } +} +function queuePostFlushCb(cb) { + if (!isArray(cb)) { + if (activePostFlushCbs && cb.id === -1) { + activePostFlushCbs.splice(postFlushIndex + 1, 0, cb); + } else if (!(cb.flags & 1)) { + pendingPostFlushCbs.push(cb); + cb.flags |= 1; + } + } else { + pendingPostFlushCbs.push(...cb); + } + queueFlush(); +} +function flushPreFlushCbs(instance, seen, i = flushIndex + 1) { + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (; i < queue.length; i++) { + const cb = queue[i]; + if (cb && cb.flags & 2) { + if (instance && cb.id !== instance.uid) { + continue; + } + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + queue.splice(i, 1); + i--; + if (cb.flags & 4) { + cb.flags &= -2; + } + cb(); + if (!(cb.flags & 4)) { + cb.flags &= -2; + } + } + } +} +function flushPostFlushCbs(seen) { + if (pendingPostFlushCbs.length) { + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); + pendingPostFlushCbs.length = 0; + if (activePostFlushCbs) { + activePostFlushCbs.push(...deduped); + return; + } + activePostFlushCbs = deduped; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + const cb = activePostFlushCbs[postFlushIndex]; + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + if (cb.flags & 4) { + cb.flags &= -2; + } + if (!(cb.flags & 8)) cb(); + cb.flags &= -2; + } + activePostFlushCbs = null; + postFlushIndex = 0; + } +} +var getId = (job) => job.id == null ? job.flags & 2 ? -1 : Infinity : job.id; +function flushJobs(seen) { + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + const check = true ? (job) => checkRecursiveUpdates(seen, job) : NOOP; + try { + for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job && !(job.flags & 8)) { + if (check(job)) { + continue; + } + if (job.flags & 4) { + job.flags &= ~1; + } + callWithErrorHandling( + job, + job.i, + job.i ? 15 : 14 + ); + if (!(job.flags & 4)) { + job.flags &= ~1; + } + } + } + } finally { + for (; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job) { + job.flags &= -2; + } + } + flushIndex = -1; + queue.length = 0; + flushPostFlushCbs(seen); + currentFlushPromise = null; + if (queue.length || pendingPostFlushCbs.length) { + flushJobs(seen); + } + } +} +function checkRecursiveUpdates(seen, fn) { + const count = seen.get(fn) || 0; + if (count > RECURSION_LIMIT) { + const instance = fn.i; + const componentName = instance && getComponentName(instance.type); + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 + ); + return true; + } + seen.set(fn, count + 1); + return false; +} +var isHmrUpdating = false; +var hmrDirtyComponents = /* @__PURE__ */ new Map(); +if (true) { + getGlobalThis().__VUE_HMR_RUNTIME__ = { + createRecord: tryWrap(createRecord), + rerender: tryWrap(rerender), + reload: tryWrap(reload) + }; +} +var map = /* @__PURE__ */ new Map(); +function registerHMR(instance) { + const id = instance.type.__hmrId; + let record = map.get(id); + if (!record) { + createRecord(id, instance.type); + record = map.get(id); + } + record.instances.add(instance); +} +function unregisterHMR(instance) { + map.get(instance.type.__hmrId).instances.delete(instance); +} +function createRecord(id, initialDef) { + if (map.has(id)) { + return false; + } + map.set(id, { + initialDef: normalizeClassComponent(initialDef), + instances: /* @__PURE__ */ new Set() + }); + return true; +} +function normalizeClassComponent(component) { + return isClassComponent(component) ? component.__vccOpts : component; +} +function rerender(id, newRender) { + const record = map.get(id); + if (!record) { + return; + } + record.initialDef.render = newRender; + [...record.instances].forEach((instance) => { + if (newRender) { + instance.render = newRender; + normalizeClassComponent(instance.type).render = newRender; + } + instance.renderCache = []; + isHmrUpdating = true; + instance.update(); + isHmrUpdating = false; + }); +} +function reload(id, newComp) { + const record = map.get(id); + if (!record) return; + newComp = normalizeClassComponent(newComp); + updateComponentDef(record.initialDef, newComp); + const instances = [...record.instances]; + for (let i = 0; i < instances.length; i++) { + const instance = instances[i]; + const oldComp = normalizeClassComponent(instance.type); + let dirtyInstances = hmrDirtyComponents.get(oldComp); + if (!dirtyInstances) { + if (oldComp !== record.initialDef) { + updateComponentDef(oldComp, newComp); + } + hmrDirtyComponents.set(oldComp, dirtyInstances = /* @__PURE__ */ new Set()); + } + dirtyInstances.add(instance); + instance.appContext.propsCache.delete(instance.type); + instance.appContext.emitsCache.delete(instance.type); + instance.appContext.optionsCache.delete(instance.type); + if (instance.ceReload) { + dirtyInstances.add(instance); + instance.ceReload(newComp.styles); + dirtyInstances.delete(instance); + } else if (instance.parent) { + queueJob(() => { + isHmrUpdating = true; + instance.parent.update(); + isHmrUpdating = false; + dirtyInstances.delete(instance); + }); + } else if (instance.appContext.reload) { + instance.appContext.reload(); + } else if (typeof window !== "undefined") { + window.location.reload(); + } else { + console.warn( + "[HMR] Root or manually mounted instance modified. Full reload required." + ); + } + if (instance.root.ce && instance !== instance.root) { + instance.root.ce._removeChildStyle(oldComp); + } + } + queuePostFlushCb(() => { + hmrDirtyComponents.clear(); + }); +} +function updateComponentDef(oldComp, newComp) { + extend(oldComp, newComp); + for (const key in oldComp) { + if (key !== "__file" && !(key in newComp)) { + delete oldComp[key]; + } + } +} +function tryWrap(fn) { + return (id, arg) => { + try { + return fn(id, arg); + } catch (e) { + console.error(e); + console.warn( + `[HMR] Something went wrong during Vue component hot-reload. Full reload required.` + ); + } + }; +} +var devtools$1; +var buffer = []; +var devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools$1) { + devtools$1.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook$1(hook, target) { + var _a, _b; + devtools$1 = hook; + if (devtools$1) { + devtools$1.enabled = true; + buffer.forEach(({ event, args }) => devtools$1.emit(event, ...args)); + buffer = []; + } else if ( + // handle late devtools injection - only do this if we are in an actual + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + // eslint-disable-next-line no-restricted-syntax + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook$1(newHook, target); + }); + setTimeout(() => { + if (!devtools$1) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +function devtoolsUnmountApp(app) { + emit$1("app:unmount", app); +} +var devtoolsComponentAdded = createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +var devtoolsComponentUpdated = createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +var _devtoolsComponentRemoved = createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +var devtoolsComponentRemoved = (component) => { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + component.parent ? component.parent.uid : void 0, + component + ); + }; +} +var devtoolsPerfStart = createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +var devtoolsPerfEnd = createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} +var currentRenderingInstance = null; +var currentScopeId = null; +function setCurrentRenderingInstance(instance) { + const prev = currentRenderingInstance; + currentRenderingInstance = instance; + currentScopeId = instance && instance.type.__scopeId || null; + return prev; +} +function pushScopeId(id) { + currentScopeId = id; +} +function popScopeId() { + currentScopeId = null; +} +var withScopeId = (_id) => withCtx; +function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { + if (!ctx) return fn; + if (fn._n) { + return fn; + } + const renderFnWithContext = (...args) => { + if (renderFnWithContext._d) { + setBlockTracking(-1); + } + const prevInstance = setCurrentRenderingInstance(ctx); + let res; + try { + res = fn(...args); + } finally { + setCurrentRenderingInstance(prevInstance); + if (renderFnWithContext._d) { + setBlockTracking(1); + } + } + if (true) { + devtoolsComponentUpdated(ctx); + } + return res; + }; + renderFnWithContext._n = true; + renderFnWithContext._c = true; + renderFnWithContext._d = true; + return renderFnWithContext; +} +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} +function withDirectives(vnode, directives) { + if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); + return vnode; + } + const instance = getComponentPublicInstance(currentRenderingInstance); + const bindings = vnode.dirs || (vnode.dirs = []); + for (let i = 0; i < directives.length; i++) { + let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]; + if (dir) { + if (isFunction(dir)) { + dir = { + mounted: dir, + updated: dir + }; + } + if (dir.deep) { + traverse(value); + } + bindings.push({ + dir, + instance, + value, + oldValue: void 0, + arg, + modifiers + }); + } + } + return vnode; +} +function invokeDirectiveHook(vnode, prevVNode, instance, name) { + const bindings = vnode.dirs; + const oldBindings = prevVNode && prevVNode.dirs; + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i]; + if (oldBindings) { + binding.oldValue = oldBindings[i].value; + } + let hook = binding.dir[name]; + if (hook) { + pauseTracking(); + callWithAsyncErrorHandling(hook, instance, 8, [ + vnode.el, + binding, + vnode, + prevVNode + ]); + resetTracking(); + } + } +} +var TeleportEndKey = Symbol("_vte"); +var isTeleport = (type) => type.__isTeleport; +var isTeleportDisabled = (props) => props && (props.disabled || props.disabled === ""); +var isTeleportDeferred = (props) => props && (props.defer || props.defer === ""); +var isTargetSVG = (target) => typeof SVGElement !== "undefined" && target instanceof SVGElement; +var isTargetMathML = (target) => typeof MathMLElement === "function" && target instanceof MathMLElement; +var resolveTarget = (props, select) => { + const targetSelector = props && props.to; + if (isString(targetSelector)) { + if (!select) { + warn$1( + `Current renderer does not support string target for Teleports. (missing querySelector renderer option)` + ); + return null; + } else { + const target = select(targetSelector); + if (!target && !isTeleportDisabled(props)) { + warn$1( + `Failed to locate Teleport target with selector "${targetSelector}". Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree.` + ); + } + return target; + } + } else { + if (!targetSelector && !isTeleportDisabled(props)) { + warn$1(`Invalid Teleport target: ${targetSelector}`); + } + return targetSelector; + } +}; +var TeleportImpl = { + name: "Teleport", + __isTeleport: true, + process(n1, n2, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, internals) { + const { + mc: mountChildren, + pc: patchChildren, + pbc: patchBlockChildren, + o: { insert, querySelector, createText, createComment } + } = internals; + const disabled = isTeleportDisabled(n2.props); + let { shapeFlag, children, dynamicChildren } = n2; + if (isHmrUpdating) { + optimized = false; + dynamicChildren = null; + } + if (n1 == null) { + const placeholder = n2.el = true ? createComment("teleport start") : createText(""); + const mainAnchor = n2.anchor = true ? createComment("teleport end") : createText(""); + insert(placeholder, container, anchor); + insert(mainAnchor, container, anchor); + const mount = (container2, anchor2) => { + if (shapeFlag & 16) { + if (parentComponent && parentComponent.isCE) { + parentComponent.ce._teleportTarget = container2; + } + mountChildren( + children, + container2, + anchor2, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + optimized + ); + } + }; + const mountToTarget = () => { + const target = n2.target = resolveTarget(n2.props, querySelector); + const targetAnchor = prepareAnchor(target, n2, createText, insert); + if (target) { + if (namespace !== "svg" && isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace !== "mathml" && isTargetMathML(target)) { + namespace = "mathml"; + } + if (!disabled) { + mount(target, targetAnchor); + updateCssVars(n2, false); + } + } else if (!disabled) { + warn$1( + "Invalid Teleport target on mount:", + target, + `(${typeof target})` + ); + } + }; + if (disabled) { + mount(container, mainAnchor); + updateCssVars(n2, true); + } + if (isTeleportDeferred(n2.props)) { + n2.el.__isMounted = false; + queuePostRenderEffect(() => { + mountToTarget(); + delete n2.el.__isMounted; + }, parentSuspense); + } else { + mountToTarget(); + } + } else { + if (isTeleportDeferred(n2.props) && n1.el.__isMounted === false) { + queuePostRenderEffect(() => { + TeleportImpl.process( + n1, + n2, + container, + anchor, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + optimized, + internals + ); + }, parentSuspense); + return; + } + n2.el = n1.el; + n2.targetStart = n1.targetStart; + const mainAnchor = n2.anchor = n1.anchor; + const target = n2.target = n1.target; + const targetAnchor = n2.targetAnchor = n1.targetAnchor; + const wasDisabled = isTeleportDisabled(n1.props); + const currentContainer = wasDisabled ? container : target; + const currentAnchor = wasDisabled ? mainAnchor : targetAnchor; + if (namespace === "svg" || isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace === "mathml" || isTargetMathML(target)) { + namespace = "mathml"; + } + if (dynamicChildren) { + patchBlockChildren( + n1.dynamicChildren, + dynamicChildren, + currentContainer, + parentComponent, + parentSuspense, + namespace, + slotScopeIds + ); + traverseStaticChildren(n1, n2, false); + } else if (!optimized) { + patchChildren( + n1, + n2, + currentContainer, + currentAnchor, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + false + ); + } + if (disabled) { + if (!wasDisabled) { + moveTeleport( + n2, + container, + mainAnchor, + internals, + 1 + ); + } else { + if (n2.props && n1.props && n2.props.to !== n1.props.to) { + n2.props.to = n1.props.to; + } + } + } else { + if ((n2.props && n2.props.to) !== (n1.props && n1.props.to)) { + const nextTarget = n2.target = resolveTarget( + n2.props, + querySelector + ); + if (nextTarget) { + moveTeleport( + n2, + nextTarget, + null, + internals, + 0 + ); + } else if (true) { + warn$1( + "Invalid Teleport target on update:", + target, + `(${typeof target})` + ); + } + } else if (wasDisabled) { + moveTeleport( + n2, + target, + targetAnchor, + internals, + 1 + ); + } + } + updateCssVars(n2, disabled); + } + }, + remove(vnode, parentComponent, parentSuspense, { um: unmount, o: { remove: hostRemove } }, doRemove) { + const { + shapeFlag, + children, + anchor, + targetStart, + targetAnchor, + target, + props + } = vnode; + if (target) { + hostRemove(targetStart); + hostRemove(targetAnchor); + } + doRemove && hostRemove(anchor); + if (shapeFlag & 16) { + const shouldRemove = doRemove || !isTeleportDisabled(props); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + unmount( + child, + parentComponent, + parentSuspense, + shouldRemove, + !!child.dynamicChildren + ); + } + } + }, + move: moveTeleport, + hydrate: hydrateTeleport +}; +function moveTeleport(vnode, container, parentAnchor, { o: { insert }, m: move }, moveType = 2) { + if (moveType === 0) { + insert(vnode.targetAnchor, container, parentAnchor); + } + const { el, anchor, shapeFlag, children, props } = vnode; + const isReorder = moveType === 2; + if (isReorder) { + insert(el, container, parentAnchor); + } + if (!isReorder || isTeleportDisabled(props)) { + if (shapeFlag & 16) { + for (let i = 0; i < children.length; i++) { + move( + children[i], + container, + parentAnchor, + 2 + ); + } + } + } + if (isReorder) { + insert(anchor, container, parentAnchor); + } +} +function hydrateTeleport(node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized, { + o: { nextSibling, parentNode, querySelector, insert, createText } +}, hydrateChildren) { + const target = vnode.target = resolveTarget( + vnode.props, + querySelector + ); + if (target) { + const disabled = isTeleportDisabled(vnode.props); + const targetNode = target._lpa || target.firstChild; + if (vnode.shapeFlag & 16) { + if (disabled) { + vnode.anchor = hydrateChildren( + nextSibling(node), + vnode, + parentNode(node), + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + vnode.targetStart = targetNode; + vnode.targetAnchor = targetNode && nextSibling(targetNode); + } else { + vnode.anchor = nextSibling(node); + let targetAnchor = targetNode; + while (targetAnchor) { + if (targetAnchor && targetAnchor.nodeType === 8) { + if (targetAnchor.data === "teleport start anchor") { + vnode.targetStart = targetAnchor; + } else if (targetAnchor.data === "teleport anchor") { + vnode.targetAnchor = targetAnchor; + target._lpa = vnode.targetAnchor && nextSibling(vnode.targetAnchor); + break; + } + } + targetAnchor = nextSibling(targetAnchor); + } + if (!vnode.targetAnchor) { + prepareAnchor(target, vnode, createText, insert); + } + hydrateChildren( + targetNode && nextSibling(targetNode), + vnode, + target, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } + updateCssVars(vnode, disabled); + } + return vnode.anchor && nextSibling(vnode.anchor); +} +var Teleport = TeleportImpl; +function updateCssVars(vnode, isDisabled) { + const ctx = vnode.ctx; + if (ctx && ctx.ut) { + let node, anchor; + if (isDisabled) { + node = vnode.el; + anchor = vnode.anchor; + } else { + node = vnode.targetStart; + anchor = vnode.targetAnchor; + } + while (node && node !== anchor) { + if (node.nodeType === 1) node.setAttribute("data-v-owner", ctx.uid); + node = node.nextSibling; + } + ctx.ut(); + } +} +function prepareAnchor(target, vnode, createText, insert) { + const targetStart = vnode.targetStart = createText(""); + const targetAnchor = vnode.targetAnchor = createText(""); + targetStart[TeleportEndKey] = targetAnchor; + if (target) { + insert(targetStart, target); + insert(targetAnchor, target); + } + return targetAnchor; +} +var leaveCbKey = Symbol("_leaveCb"); +var enterCbKey = Symbol("_enterCb"); +function useTransitionState() { + const state = { + isMounted: false, + isLeaving: false, + isUnmounting: false, + leavingVNodes: /* @__PURE__ */ new Map() + }; + onMounted(() => { + state.isMounted = true; + }); + onBeforeUnmount(() => { + state.isUnmounting = true; + }); + return state; +} +var TransitionHookValidator = [Function, Array]; +var BaseTransitionPropsValidators = { + mode: String, + appear: Boolean, + persisted: Boolean, + // enter + onBeforeEnter: TransitionHookValidator, + onEnter: TransitionHookValidator, + onAfterEnter: TransitionHookValidator, + onEnterCancelled: TransitionHookValidator, + // leave + onBeforeLeave: TransitionHookValidator, + onLeave: TransitionHookValidator, + onAfterLeave: TransitionHookValidator, + onLeaveCancelled: TransitionHookValidator, + // appear + onBeforeAppear: TransitionHookValidator, + onAppear: TransitionHookValidator, + onAfterAppear: TransitionHookValidator, + onAppearCancelled: TransitionHookValidator +}; +var recursiveGetSubtree = (instance) => { + const subTree = instance.subTree; + return subTree.component ? recursiveGetSubtree(subTree.component) : subTree; +}; +var BaseTransitionImpl = { + name: `BaseTransition`, + props: BaseTransitionPropsValidators, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const state = useTransitionState(); + return () => { + const children = slots.default && getTransitionRawChildren(slots.default(), true); + if (!children || !children.length) { + return; + } + const child = findNonCommentChild(children); + const rawProps = toRaw(props); + const { mode } = rawProps; + if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { + warn$1(`invalid mode: ${mode}`); + } + if (state.isLeaving) { + return emptyPlaceholder(child); + } + const innerChild = getInnerChild$1(child); + if (!innerChild) { + return emptyPlaceholder(child); + } + let enterHooks = resolveTransitionHooks( + innerChild, + rawProps, + state, + instance, + // #11061, ensure enterHooks is fresh after clone + (hooks) => enterHooks = hooks + ); + if (innerChild.type !== Comment) { + setTransitionHooks(innerChild, enterHooks); + } + let oldInnerChild = instance.subTree && getInnerChild$1(instance.subTree); + if (oldInnerChild && oldInnerChild.type !== Comment && !isSameVNodeType(innerChild, oldInnerChild) && recursiveGetSubtree(instance).type !== Comment) { + let leavingHooks = resolveTransitionHooks( + oldInnerChild, + rawProps, + state, + instance + ); + setTransitionHooks(oldInnerChild, leavingHooks); + if (mode === "out-in" && innerChild.type !== Comment) { + state.isLeaving = true; + leavingHooks.afterLeave = () => { + state.isLeaving = false; + if (!(instance.job.flags & 8)) { + instance.update(); + } + delete leavingHooks.afterLeave; + oldInnerChild = void 0; + }; + return emptyPlaceholder(child); + } else if (mode === "in-out" && innerChild.type !== Comment) { + leavingHooks.delayLeave = (el, earlyRemove, delayedLeave) => { + const leavingVNodesCache = getLeavingNodesForType( + state, + oldInnerChild + ); + leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild; + el[leaveCbKey] = () => { + earlyRemove(); + el[leaveCbKey] = void 0; + delete enterHooks.delayedLeave; + oldInnerChild = void 0; + }; + enterHooks.delayedLeave = () => { + delayedLeave(); + delete enterHooks.delayedLeave; + oldInnerChild = void 0; + }; + }; + } else { + oldInnerChild = void 0; + } + } else if (oldInnerChild) { + oldInnerChild = void 0; + } + return child; + }; + } +}; +function findNonCommentChild(children) { + let child = children[0]; + if (children.length > 1) { + let hasFound = false; + for (const c of children) { + if (c.type !== Comment) { + if (hasFound) { + warn$1( + " can only be used on a single element or component. Use for lists." + ); + break; + } + child = c; + hasFound = true; + if (false) break; + } + } + } + return child; +} +var BaseTransition = BaseTransitionImpl; +function getLeavingNodesForType(state, vnode) { + const { leavingVNodes } = state; + let leavingVNodesCache = leavingVNodes.get(vnode.type); + if (!leavingVNodesCache) { + leavingVNodesCache = /* @__PURE__ */ Object.create(null); + leavingVNodes.set(vnode.type, leavingVNodesCache); + } + return leavingVNodesCache; +} +function resolveTransitionHooks(vnode, props, state, instance, postClone) { + const { + appear, + mode, + persisted = false, + onBeforeEnter, + onEnter, + onAfterEnter, + onEnterCancelled, + onBeforeLeave, + onLeave, + onAfterLeave, + onLeaveCancelled, + onBeforeAppear, + onAppear, + onAfterAppear, + onAppearCancelled + } = props; + const key = String(vnode.key); + const leavingVNodesCache = getLeavingNodesForType(state, vnode); + const callHook3 = (hook, args) => { + hook && callWithAsyncErrorHandling( + hook, + instance, + 9, + args + ); + }; + const callAsyncHook = (hook, args) => { + const done = args[1]; + callHook3(hook, args); + if (isArray(hook)) { + if (hook.every((hook2) => hook2.length <= 1)) done(); + } else if (hook.length <= 1) { + done(); + } + }; + const hooks = { + mode, + persisted, + beforeEnter(el) { + let hook = onBeforeEnter; + if (!state.isMounted) { + if (appear) { + hook = onBeforeAppear || onBeforeEnter; + } else { + return; + } + } + if (el[leaveCbKey]) { + el[leaveCbKey]( + true + /* cancelled */ + ); + } + const leavingVNode = leavingVNodesCache[key]; + if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el[leaveCbKey]) { + leavingVNode.el[leaveCbKey](); + } + callHook3(hook, [el]); + }, + enter(el) { + let hook = onEnter; + let afterHook = onAfterEnter; + let cancelHook = onEnterCancelled; + if (!state.isMounted) { + if (appear) { + hook = onAppear || onEnter; + afterHook = onAfterAppear || onAfterEnter; + cancelHook = onAppearCancelled || onEnterCancelled; + } else { + return; + } + } + let called = false; + const done = el[enterCbKey] = (cancelled) => { + if (called) return; + called = true; + if (cancelled) { + callHook3(cancelHook, [el]); + } else { + callHook3(afterHook, [el]); + } + if (hooks.delayedLeave) { + hooks.delayedLeave(); + } + el[enterCbKey] = void 0; + }; + if (hook) { + callAsyncHook(hook, [el, done]); + } else { + done(); + } + }, + leave(el, remove2) { + const key2 = String(vnode.key); + if (el[enterCbKey]) { + el[enterCbKey]( + true + /* cancelled */ + ); + } + if (state.isUnmounting) { + return remove2(); + } + callHook3(onBeforeLeave, [el]); + let called = false; + const done = el[leaveCbKey] = (cancelled) => { + if (called) return; + called = true; + remove2(); + if (cancelled) { + callHook3(onLeaveCancelled, [el]); + } else { + callHook3(onAfterLeave, [el]); + } + el[leaveCbKey] = void 0; + if (leavingVNodesCache[key2] === vnode) { + delete leavingVNodesCache[key2]; + } + }; + leavingVNodesCache[key2] = vnode; + if (onLeave) { + callAsyncHook(onLeave, [el, done]); + } else { + done(); + } + }, + clone(vnode2) { + const hooks2 = resolveTransitionHooks( + vnode2, + props, + state, + instance, + postClone + ); + if (postClone) postClone(hooks2); + return hooks2; + } + }; + return hooks; +} +function emptyPlaceholder(vnode) { + if (isKeepAlive(vnode)) { + vnode = cloneVNode(vnode); + vnode.children = null; + return vnode; + } +} +function getInnerChild$1(vnode) { + if (!isKeepAlive(vnode)) { + if (isTeleport(vnode.type) && vnode.children) { + return findNonCommentChild(vnode.children); + } + return vnode; + } + if (vnode.component) { + return vnode.component.subTree; + } + const { shapeFlag, children } = vnode; + if (children) { + if (shapeFlag & 16) { + return children[0]; + } + if (shapeFlag & 32 && isFunction(children.default)) { + return children.default(); + } + } +} +function setTransitionHooks(vnode, hooks) { + if (vnode.shapeFlag & 6 && vnode.component) { + vnode.transition = hooks; + setTransitionHooks(vnode.component.subTree, hooks); + } else if (vnode.shapeFlag & 128) { + vnode.ssContent.transition = hooks.clone(vnode.ssContent); + vnode.ssFallback.transition = hooks.clone(vnode.ssFallback); + } else { + vnode.transition = hooks; + } +} +function getTransitionRawChildren(children, keepComment = false, parentKey) { + let ret = []; + let keyedFragmentCount = 0; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + const key = parentKey == null ? child.key : String(parentKey) + String(child.key != null ? child.key : i); + if (child.type === Fragment) { + if (child.patchFlag & 128) keyedFragmentCount++; + ret = ret.concat( + getTransitionRawChildren(child.children, keepComment, key) + ); + } else if (keepComment || child.type !== Comment) { + ret.push(key != null ? cloneVNode(child, { key }) : child); + } + } + if (keyedFragmentCount > 1) { + for (let i = 0; i < ret.length; i++) { + ret[i].patchFlag = -2; + } + } + return ret; +} +function defineComponent(options, extraOptions) { + return isFunction(options) ? ( + // #8236: extend call and options.name access are considered side-effects + // by Rollup, so we have to wrap it in a pure-annotated IIFE. + (() => extend({ name: options.name }, extraOptions, { setup: options }))() + ) : options; +} +function useId() { + const i = getCurrentInstance(); + if (i) { + return (i.appContext.config.idPrefix || "v") + "-" + i.ids[0] + i.ids[1]++; + } else if (true) { + warn$1( + `useId() is called when there is no active component instance to be associated with.` + ); + } + return ""; +} +function markAsyncBoundary(instance) { + instance.ids = [instance.ids[0] + instance.ids[2]++ + "-", 0, 0]; +} +var knownTemplateRefs = /* @__PURE__ */ new WeakSet(); +function useTemplateRef(key) { + const i = getCurrentInstance(); + const r = shallowRef(null); + if (i) { + const refs = i.refs === EMPTY_OBJ ? i.refs = {} : i.refs; + let desc; + if ((desc = Object.getOwnPropertyDescriptor(refs, key)) && !desc.configurable) { + warn$1(`useTemplateRef('${key}') already exists.`); + } else { + Object.defineProperty(refs, key, { + enumerable: true, + get: () => r.value, + set: (val) => r.value = val + }); + } + } else if (true) { + warn$1( + `useTemplateRef() is called when there is no active component instance to be associated with.` + ); + } + const ret = true ? readonly(r) : r; + if (true) { + knownTemplateRefs.add(ret); + } + return ret; +} +function setRef(rawRef, oldRawRef, parentSuspense, vnode, isUnmount = false) { + if (isArray(rawRef)) { + rawRef.forEach( + (r, i) => setRef( + r, + oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef), + parentSuspense, + vnode, + isUnmount + ) + ); + return; + } + if (isAsyncWrapper(vnode) && !isUnmount) { + if (vnode.shapeFlag & 512 && vnode.type.__asyncResolved && vnode.component.subTree.component) { + setRef(rawRef, oldRawRef, parentSuspense, vnode.component.subTree); + } + return; + } + const refValue = vnode.shapeFlag & 4 ? getComponentPublicInstance(vnode.component) : vnode.el; + const value = isUnmount ? null : refValue; + const { i: owner, r: ref2 } = rawRef; + if (!owner) { + warn$1( + `Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function.` + ); + return; + } + const oldRef = oldRawRef && oldRawRef.r; + const refs = owner.refs === EMPTY_OBJ ? owner.refs = {} : owner.refs; + const setupState = owner.setupState; + const rawSetupState = toRaw(setupState); + const canSetSetupRef = setupState === EMPTY_OBJ ? () => false : (key) => { + if (true) { + if (hasOwn(rawSetupState, key) && !isRef2(rawSetupState[key])) { + warn$1( + `Template ref "${key}" used on a non-ref value. It will not work in the production build.` + ); + } + if (knownTemplateRefs.has(rawSetupState[key])) { + return false; + } + } + return hasOwn(rawSetupState, key); + }; + if (oldRef != null && oldRef !== ref2) { + if (isString(oldRef)) { + refs[oldRef] = null; + if (canSetSetupRef(oldRef)) { + setupState[oldRef] = null; + } + } else if (isRef2(oldRef)) { + oldRef.value = null; + } + } + if (isFunction(ref2)) { + callWithErrorHandling(ref2, owner, 12, [value, refs]); + } else { + const _isString = isString(ref2); + const _isRef = isRef2(ref2); + if (_isString || _isRef) { + const doSet = () => { + if (rawRef.f) { + const existing = _isString ? canSetSetupRef(ref2) ? setupState[ref2] : refs[ref2] : ref2.value; + if (isUnmount) { + isArray(existing) && remove(existing, refValue); + } else { + if (!isArray(existing)) { + if (_isString) { + refs[ref2] = [refValue]; + if (canSetSetupRef(ref2)) { + setupState[ref2] = refs[ref2]; + } + } else { + ref2.value = [refValue]; + if (rawRef.k) refs[rawRef.k] = ref2.value; + } + } else if (!existing.includes(refValue)) { + existing.push(refValue); + } + } + } else if (_isString) { + refs[ref2] = value; + if (canSetSetupRef(ref2)) { + setupState[ref2] = value; + } + } else if (_isRef) { + ref2.value = value; + if (rawRef.k) refs[rawRef.k] = value; + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + }; + if (value) { + doSet.id = -1; + queuePostRenderEffect(doSet, parentSuspense); + } else { + doSet(); + } + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + } +} +var hasLoggedMismatchError = false; +var logMismatchError = () => { + if (hasLoggedMismatchError) { + return; + } + console.error("Hydration completed but contains mismatches."); + hasLoggedMismatchError = true; +}; +var isSVGContainer = (container) => container.namespaceURI.includes("svg") && container.tagName !== "foreignObject"; +var isMathMLContainer = (container) => container.namespaceURI.includes("MathML"); +var getContainerType = (container) => { + if (container.nodeType !== 1) return void 0; + if (isSVGContainer(container)) return "svg"; + if (isMathMLContainer(container)) return "mathml"; + return void 0; +}; +var isComment = (node) => node.nodeType === 8; +function createHydrationFunctions(rendererInternals) { + const { + mt: mountComponent, + p: patch, + o: { + patchProp: patchProp2, + createText, + nextSibling, + parentNode, + remove: remove2, + insert, + createComment + } + } = rendererInternals; + const hydrate2 = (vnode, container) => { + if (!container.hasChildNodes()) { + warn$1( + `Attempting to hydrate existing markup but container is empty. Performing full mount instead.` + ); + patch(null, vnode, container); + flushPostFlushCbs(); + container._vnode = vnode; + return; + } + hydrateNode(container.firstChild, vnode, null, null, null); + flushPostFlushCbs(); + container._vnode = vnode; + }; + const hydrateNode = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized = false) => { + optimized = optimized || !!vnode.dynamicChildren; + const isFragmentStart = isComment(node) && node.data === "["; + const onMismatch = () => handleMismatch( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + isFragmentStart + ); + const { type, ref: ref2, shapeFlag, patchFlag } = vnode; + let domType = node.nodeType; + vnode.el = node; + if (true) { + def(node, "__vnode", vnode, true); + def(node, "__vueParentComponent", parentComponent, true); + } + if (patchFlag === -2) { + optimized = false; + vnode.dynamicChildren = null; + } + let nextNode = null; + switch (type) { + case Text: + if (domType !== 3) { + if (vnode.children === "") { + insert(vnode.el = createText(""), parentNode(node), node); + nextNode = node; + } else { + nextNode = onMismatch(); + } + } else { + if (node.data !== vnode.children) { + warn$1( + `Hydration text mismatch in`, + node.parentNode, + ` + - rendered on server: ${JSON.stringify( + node.data + )} + - expected on client: ${JSON.stringify(vnode.children)}` + ); + logMismatchError(); + node.data = vnode.children; + } + nextNode = nextSibling(node); + } + break; + case Comment: + if (isTemplateNode(node)) { + nextNode = nextSibling(node); + replaceNode( + vnode.el = node.content.firstChild, + node, + parentComponent + ); + } else if (domType !== 8 || isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = nextSibling(node); + } + break; + case Static: + if (isFragmentStart) { + node = nextSibling(node); + domType = node.nodeType; + } + if (domType === 1 || domType === 3) { + nextNode = node; + const needToAdoptContent = !vnode.children.length; + for (let i = 0; i < vnode.staticCount; i++) { + if (needToAdoptContent) + vnode.children += nextNode.nodeType === 1 ? nextNode.outerHTML : nextNode.data; + if (i === vnode.staticCount - 1) { + vnode.anchor = nextNode; + } + nextNode = nextSibling(nextNode); + } + return isFragmentStart ? nextSibling(nextNode) : nextNode; + } else { + onMismatch(); + } + break; + case Fragment: + if (!isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = hydrateFragment( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + break; + default: + if (shapeFlag & 1) { + if ((domType !== 1 || vnode.type.toLowerCase() !== node.tagName.toLowerCase()) && !isTemplateNode(node)) { + nextNode = onMismatch(); + } else { + nextNode = hydrateElement( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } else if (shapeFlag & 6) { + vnode.slotScopeIds = slotScopeIds; + const container = parentNode(node); + if (isFragmentStart) { + nextNode = locateClosingAnchor(node); + } else if (isComment(node) && node.data === "teleport start") { + nextNode = locateClosingAnchor(node, node.data, "teleport end"); + } else { + nextNode = nextSibling(node); + } + mountComponent( + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + optimized + ); + if (isAsyncWrapper(vnode) && !vnode.type.__asyncResolved) { + let subTree; + if (isFragmentStart) { + subTree = createVNode(Fragment); + subTree.anchor = nextNode ? nextNode.previousSibling : container.lastChild; + } else { + subTree = node.nodeType === 3 ? createTextVNode("") : createVNode("div"); + } + subTree.el = node; + vnode.component.subTree = subTree; + } + } else if (shapeFlag & 64) { + if (domType !== 8) { + nextNode = onMismatch(); + } else { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized, + rendererInternals, + hydrateChildren + ); + } + } else if (shapeFlag & 128) { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + getContainerType(parentNode(node)), + slotScopeIds, + optimized, + rendererInternals, + hydrateNode + ); + } else if (true) { + warn$1("Invalid HostVNode type:", type, `(${typeof type})`); + } + } + if (ref2 != null) { + setRef(ref2, null, parentSuspense, vnode); + } + return nextNode; + }; + const hydrateElement = (el, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!vnode.dynamicChildren; + const { type, props, patchFlag, shapeFlag, dirs, transition } = vnode; + const forcePatch = type === "input" || type === "option"; + if (true) { + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "created"); + } + let needCallTransitionHooks = false; + if (isTemplateNode(el)) { + needCallTransitionHooks = needTransition( + null, + // no need check parentSuspense in hydration + transition + ) && parentComponent && parentComponent.vnode.props && parentComponent.vnode.props.appear; + const content = el.content.firstChild; + if (needCallTransitionHooks) { + const cls = content.getAttribute("class"); + if (cls) content.$cls = cls; + transition.beforeEnter(content); + } + replaceNode(content, el, parentComponent); + vnode.el = el = content; + } + if (shapeFlag & 16 && // skip if element has innerHTML / textContent + !(props && (props.innerHTML || props.textContent))) { + let next = hydrateChildren( + el.firstChild, + vnode, + el, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + let hasWarned2 = false; + while (next) { + if (!isMismatchAllowed( + el, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + el, + ` +Server rendered element contains more child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + const cur = next; + next = next.nextSibling; + remove2(cur); + } + } else if (shapeFlag & 8) { + let clientText = vnode.children; + if (clientText[0] === "\n" && (el.tagName === "PRE" || el.tagName === "TEXTAREA")) { + clientText = clientText.slice(1); + } + if (el.textContent !== clientText) { + if (!isMismatchAllowed( + el, + 0 + /* TEXT */ + )) { + warn$1( + `Hydration text content mismatch on`, + el, + ` + - rendered on server: ${el.textContent} + - expected on client: ${vnode.children}` + ); + logMismatchError(); + } + el.textContent = vnode.children; + } + } + if (props) { + if (true) { + const isCustomElement = el.tagName.includes("-"); + for (const key in props) { + if (// #11189 skip if this node has directives that have created hooks + // as it could have mutated the DOM in any possible way + !(dirs && dirs.some((d) => d.dir.created)) && propHasMismatch(el, key, props[key], vnode, parentComponent)) { + logMismatchError(); + } + if (forcePatch && (key.endsWith("value") || key === "indeterminate") || isOn(key) && !isReservedProp(key) || // force hydrate v-bind with .prop modifiers + key[0] === "." || isCustomElement) { + patchProp2(el, key, null, props[key], void 0, parentComponent); + } + } + } else if (props.onClick) { + patchProp2( + el, + "onClick", + null, + props.onClick, + void 0, + parentComponent + ); + } else if (patchFlag & 4 && isReactive(props.style)) { + for (const key in props.style) props.style[key]; + } + } + let vnodeHooks; + if (vnodeHooks = props && props.onVnodeBeforeMount) { + invokeVNodeHook(vnodeHooks, parentComponent, vnode); + } + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "beforeMount"); + } + if ((vnodeHooks = props && props.onVnodeMounted) || dirs || needCallTransitionHooks) { + queueEffectWithSuspense(() => { + vnodeHooks && invokeVNodeHook(vnodeHooks, parentComponent, vnode); + needCallTransitionHooks && transition.enter(el); + dirs && invokeDirectiveHook(vnode, null, parentComponent, "mounted"); + }, parentSuspense); + } + } + return el.nextSibling; + }; + const hydrateChildren = (node, parentVNode, container, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!parentVNode.dynamicChildren; + const children = parentVNode.children; + const l = children.length; + let hasWarned2 = false; + for (let i = 0; i < l; i++) { + const vnode = optimized ? children[i] : children[i] = normalizeVNode(children[i]); + const isText = vnode.type === Text; + if (node) { + if (isText && !optimized) { + if (i + 1 < l && normalizeVNode(children[i + 1]).type === Text) { + insert( + createText( + node.data.slice(vnode.children.length) + ), + container, + nextSibling(node) + ); + node.data = vnode.children; + } + } + node = hydrateNode( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } else if (isText && !vnode.children) { + insert(vnode.el = createText(""), container); + } else { + if (!isMismatchAllowed( + container, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + container, + ` +Server rendered element contains fewer child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + patch( + null, + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + } + } + return node; + }; + const hydrateFragment = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + const { slotScopeIds: fragmentSlotScopeIds } = vnode; + if (fragmentSlotScopeIds) { + slotScopeIds = slotScopeIds ? slotScopeIds.concat(fragmentSlotScopeIds) : fragmentSlotScopeIds; + } + const container = parentNode(node); + const next = hydrateChildren( + nextSibling(node), + vnode, + container, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + if (next && isComment(next) && next.data === "]") { + return nextSibling(vnode.anchor = next); + } else { + logMismatchError(); + insert(vnode.anchor = createComment(`]`), container, next); + return next; + } + }; + const handleMismatch = (node, vnode, parentComponent, parentSuspense, slotScopeIds, isFragment) => { + if (!isMismatchAllowed( + node.parentElement, + 1 + /* CHILDREN */ + )) { + warn$1( + `Hydration node mismatch: +- rendered on server:`, + node, + node.nodeType === 3 ? `(text)` : isComment(node) && node.data === "[" ? `(start of fragment)` : ``, + ` +- expected on client:`, + vnode.type + ); + logMismatchError(); + } + vnode.el = null; + if (isFragment) { + const end = locateClosingAnchor(node); + while (true) { + const next2 = nextSibling(node); + if (next2 && next2 !== end) { + remove2(next2); + } else { + break; + } + } + } + const next = nextSibling(node); + const container = parentNode(node); + remove2(node); + patch( + null, + vnode, + container, + next, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + if (parentComponent) { + parentComponent.vnode.el = vnode.el; + updateHOCHostEl(parentComponent, vnode.el); + } + return next; + }; + const locateClosingAnchor = (node, open = "[", close = "]") => { + let match = 0; + while (node) { + node = nextSibling(node); + if (node && isComment(node)) { + if (node.data === open) match++; + if (node.data === close) { + if (match === 0) { + return nextSibling(node); + } else { + match--; + } + } + } + } + return node; + }; + const replaceNode = (newNode, oldNode, parentComponent) => { + const parentNode2 = oldNode.parentNode; + if (parentNode2) { + parentNode2.replaceChild(newNode, oldNode); + } + let parent = parentComponent; + while (parent) { + if (parent.vnode.el === oldNode) { + parent.vnode.el = parent.subTree.el = newNode; + } + parent = parent.parent; + } + }; + const isTemplateNode = (node) => { + return node.nodeType === 1 && node.tagName === "TEMPLATE"; + }; + return [hydrate2, hydrateNode]; +} +function propHasMismatch(el, key, clientValue, vnode, instance) { + let mismatchType; + let mismatchKey; + let actual; + let expected; + if (key === "class") { + if (el.$cls) { + actual = el.$cls; + delete el.$cls; + } else { + actual = el.getAttribute("class"); + } + expected = normalizeClass(clientValue); + if (!isSetEqual(toClassSet(actual || ""), toClassSet(expected))) { + mismatchType = 2; + mismatchKey = `class`; + } + } else if (key === "style") { + actual = el.getAttribute("style") || ""; + expected = isString(clientValue) ? clientValue : stringifyStyle(normalizeStyle(clientValue)); + const actualMap = toStyleMap(actual); + const expectedMap = toStyleMap(expected); + if (vnode.dirs) { + for (const { dir, value } of vnode.dirs) { + if (dir.name === "show" && !value) { + expectedMap.set("display", "none"); + } + } + } + if (instance) { + resolveCssVars(instance, vnode, expectedMap); + } + if (!isMapEqual(actualMap, expectedMap)) { + mismatchType = 3; + mismatchKey = "style"; + } + } else if (el instanceof SVGElement && isKnownSvgAttr(key) || el instanceof HTMLElement && (isBooleanAttr(key) || isKnownHtmlAttr(key))) { + if (isBooleanAttr(key)) { + actual = el.hasAttribute(key); + expected = includeBooleanAttr(clientValue); + } else if (clientValue == null) { + actual = el.hasAttribute(key); + expected = false; + } else { + if (el.hasAttribute(key)) { + actual = el.getAttribute(key); + } else if (key === "value" && el.tagName === "TEXTAREA") { + actual = el.value; + } else { + actual = false; + } + expected = isRenderableAttrValue(clientValue) ? String(clientValue) : false; + } + if (actual !== expected) { + mismatchType = 4; + mismatchKey = key; + } + } + if (mismatchType != null && !isMismatchAllowed(el, mismatchType)) { + const format = (v) => v === false ? `(not rendered)` : `${mismatchKey}="${v}"`; + const preSegment = `Hydration ${MismatchTypeString[mismatchType]} mismatch on`; + const postSegment = ` + - rendered on server: ${format(actual)} + - expected on client: ${format(expected)} + Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead. + You should fix the source of the mismatch.`; + { + warn$1(preSegment, el, postSegment); + } + return true; + } + return false; +} +function toClassSet(str) { + return new Set(str.trim().split(/\s+/)); +} +function isSetEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const s of a) { + if (!b.has(s)) { + return false; + } + } + return true; +} +function toStyleMap(str) { + const styleMap = /* @__PURE__ */ new Map(); + for (const item of str.split(";")) { + let [key, value] = item.split(":"); + key = key.trim(); + value = value && value.trim(); + if (key && value) { + styleMap.set(key, value); + } + } + return styleMap; +} +function isMapEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const [key, value] of a) { + if (value !== b.get(key)) { + return false; + } + } + return true; +} +function resolveCssVars(instance, vnode, expectedMap) { + const root = instance.subTree; + if (instance.getCssVars && (vnode === root || root && root.type === Fragment && root.children.includes(vnode))) { + const cssVars = instance.getCssVars(); + for (const key in cssVars) { + expectedMap.set( + `--${getEscapedCssVarName(key, false)}`, + String(cssVars[key]) + ); + } + } + if (vnode === root && instance.parent) { + resolveCssVars(instance.parent, instance.vnode, expectedMap); + } +} +var allowMismatchAttr = "data-allow-mismatch"; +var MismatchTypeString = { + [ + 0 + /* TEXT */ + ]: "text", + [ + 1 + /* CHILDREN */ + ]: "children", + [ + 2 + /* CLASS */ + ]: "class", + [ + 3 + /* STYLE */ + ]: "style", + [ + 4 + /* ATTRIBUTE */ + ]: "attribute" +}; +function isMismatchAllowed(el, allowedType) { + if (allowedType === 0 || allowedType === 1) { + while (el && !el.hasAttribute(allowMismatchAttr)) { + el = el.parentElement; + } + } + const allowedAttr = el && el.getAttribute(allowMismatchAttr); + if (allowedAttr == null) { + return false; + } else if (allowedAttr === "") { + return true; + } else { + const list = allowedAttr.split(","); + if (allowedType === 0 && list.includes("children")) { + return true; + } + return list.includes(MismatchTypeString[allowedType]); + } +} +var requestIdleCallback = getGlobalThis().requestIdleCallback || ((cb) => setTimeout(cb, 1)); +var cancelIdleCallback = getGlobalThis().cancelIdleCallback || ((id) => clearTimeout(id)); +var hydrateOnIdle = (timeout = 1e4) => (hydrate2) => { + const id = requestIdleCallback(hydrate2, { timeout }); + return () => cancelIdleCallback(id); +}; +function elementIsVisibleInViewport(el) { + const { top, left, bottom, right } = el.getBoundingClientRect(); + const { innerHeight, innerWidth } = window; + return (top > 0 && top < innerHeight || bottom > 0 && bottom < innerHeight) && (left > 0 && left < innerWidth || right > 0 && right < innerWidth); +} +var hydrateOnVisible = (opts) => (hydrate2, forEach) => { + const ob = new IntersectionObserver((entries) => { + for (const e of entries) { + if (!e.isIntersecting) continue; + ob.disconnect(); + hydrate2(); + break; + } + }, opts); + forEach((el) => { + if (!(el instanceof Element)) return; + if (elementIsVisibleInViewport(el)) { + hydrate2(); + ob.disconnect(); + return false; + } + ob.observe(el); + }); + return () => ob.disconnect(); +}; +var hydrateOnMediaQuery = (query) => (hydrate2) => { + if (query) { + const mql = matchMedia(query); + if (mql.matches) { + hydrate2(); + } else { + mql.addEventListener("change", hydrate2, { once: true }); + return () => mql.removeEventListener("change", hydrate2); + } + } +}; +var hydrateOnInteraction = (interactions = []) => (hydrate2, forEach) => { + if (isString(interactions)) interactions = [interactions]; + let hasHydrated = false; + const doHydrate = (e) => { + if (!hasHydrated) { + hasHydrated = true; + teardown(); + hydrate2(); + e.target.dispatchEvent(new e.constructor(e.type, e)); + } + }; + const teardown = () => { + forEach((el) => { + for (const i of interactions) { + el.removeEventListener(i, doHydrate); + } + }); + }; + forEach((el) => { + for (const i of interactions) { + el.addEventListener(i, doHydrate, { once: true }); + } + }); + return teardown; +}; +function forEachElement(node, cb) { + if (isComment(node) && node.data === "[") { + let depth = 1; + let next = node.nextSibling; + while (next) { + if (next.nodeType === 1) { + const result = cb(next); + if (result === false) { + break; + } + } else if (isComment(next)) { + if (next.data === "]") { + if (--depth === 0) break; + } else if (next.data === "[") { + depth++; + } + } + next = next.nextSibling; + } + } else { + cb(node); + } +} +var isAsyncWrapper = (i) => !!i.type.__asyncLoader; +function defineAsyncComponent(source) { + if (isFunction(source)) { + source = { loader: source }; + } + const { + loader, + loadingComponent, + errorComponent, + delay = 200, + hydrate: hydrateStrategy, + timeout, + // undefined = never times out + suspensible = true, + onError: userOnError + } = source; + let pendingRequest = null; + let resolvedComp; + let retries = 0; + const retry = () => { + retries++; + pendingRequest = null; + return load(); + }; + const load = () => { + let thisRequest; + return pendingRequest || (thisRequest = pendingRequest = loader().catch((err) => { + err = err instanceof Error ? err : new Error(String(err)); + if (userOnError) { + return new Promise((resolve2, reject) => { + const userRetry = () => resolve2(retry()); + const userFail = () => reject(err); + userOnError(err, userRetry, userFail, retries + 1); + }); + } else { + throw err; + } + }).then((comp) => { + if (thisRequest !== pendingRequest && pendingRequest) { + return pendingRequest; + } + if (!comp) { + warn$1( + `Async component loader resolved to undefined. If you are using retry(), make sure to return its return value.` + ); + } + if (comp && (comp.__esModule || comp[Symbol.toStringTag] === "Module")) { + comp = comp.default; + } + if (comp && !isObject(comp) && !isFunction(comp)) { + throw new Error(`Invalid async component load result: ${comp}`); + } + resolvedComp = comp; + return comp; + })); + }; + return defineComponent({ + name: "AsyncComponentWrapper", + __asyncLoader: load, + __asyncHydrate(el, instance, hydrate2) { + let patched = false; + const doHydrate = hydrateStrategy ? () => { + const performHydrate = () => { + if (patched) { + warn$1( + `Skipping lazy hydration for component '${getComponentName(resolvedComp)}': it was updated before lazy hydration performed.` + ); + return; + } + hydrate2(); + }; + const teardown = hydrateStrategy( + performHydrate, + (cb) => forEachElement(el, cb) + ); + if (teardown) { + (instance.bum || (instance.bum = [])).push(teardown); + } + (instance.u || (instance.u = [])).push(() => patched = true); + } : hydrate2; + if (resolvedComp) { + doHydrate(); + } else { + load().then(() => !instance.isUnmounted && doHydrate()); + } + }, + get __asyncResolved() { + return resolvedComp; + }, + setup() { + const instance = currentInstance; + markAsyncBoundary(instance); + if (resolvedComp) { + return () => createInnerComp(resolvedComp, instance); + } + const onError = (err) => { + pendingRequest = null; + handleError( + err, + instance, + 13, + !errorComponent + ); + }; + if (suspensible && instance.suspense || isInSSRComponentSetup) { + return load().then((comp) => { + return () => createInnerComp(comp, instance); + }).catch((err) => { + onError(err); + return () => errorComponent ? createVNode(errorComponent, { + error: err + }) : null; + }); + } + const loaded = ref(false); + const error = ref(); + const delayed = ref(!!delay); + if (delay) { + setTimeout(() => { + delayed.value = false; + }, delay); + } + if (timeout != null) { + setTimeout(() => { + if (!loaded.value && !error.value) { + const err = new Error( + `Async component timed out after ${timeout}ms.` + ); + onError(err); + error.value = err; + } + }, timeout); + } + load().then(() => { + loaded.value = true; + if (instance.parent && isKeepAlive(instance.parent.vnode)) { + instance.parent.update(); + } + }).catch((err) => { + onError(err); + error.value = err; + }); + return () => { + if (loaded.value && resolvedComp) { + return createInnerComp(resolvedComp, instance); + } else if (error.value && errorComponent) { + return createVNode(errorComponent, { + error: error.value + }); + } else if (loadingComponent && !delayed.value) { + return createVNode(loadingComponent); + } + }; + } + }); +} +function createInnerComp(comp, parent) { + const { ref: ref2, props, children, ce } = parent.vnode; + const vnode = createVNode(comp, props, children); + vnode.ref = ref2; + vnode.ce = ce; + delete parent.vnode.ce; + return vnode; +} +var isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +var KeepAliveImpl = { + name: `KeepAlive`, + // Marker for special handling inside the renderer. We are not using a === + // check directly on KeepAlive in the renderer, because importing it directly + // would prevent it from being tree-shaken. + __isKeepAlive: true, + props: { + include: [String, RegExp, Array], + exclude: [String, RegExp, Array], + max: [String, Number] + }, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const sharedContext = instance.ctx; + if (!sharedContext.renderer) { + return () => { + const children = slots.default && slots.default(); + return children && children.length === 1 ? children[0] : children; + }; + } + const cache = /* @__PURE__ */ new Map(); + const keys = /* @__PURE__ */ new Set(); + let current = null; + if (true) { + instance.__v_cache = cache; + } + const parentSuspense = instance.suspense; + const { + renderer: { + p: patch, + m: move, + um: _unmount, + o: { createElement } + } + } = sharedContext; + const storageContainer = createElement("div"); + sharedContext.activate = (vnode, container, anchor, namespace, optimized) => { + const instance2 = vnode.component; + move(vnode, container, anchor, 0, parentSuspense); + patch( + instance2.vnode, + vnode, + container, + anchor, + instance2, + parentSuspense, + namespace, + vnode.slotScopeIds, + optimized + ); + queuePostRenderEffect(() => { + instance2.isDeactivated = false; + if (instance2.a) { + invokeArrayFns(instance2.a); + } + const vnodeHook = vnode.props && vnode.props.onVnodeMounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + sharedContext.deactivate = (vnode) => { + const instance2 = vnode.component; + invalidateMount(instance2.m); + invalidateMount(instance2.a); + move(vnode, storageContainer, null, 1, parentSuspense); + queuePostRenderEffect(() => { + if (instance2.da) { + invokeArrayFns(instance2.da); + } + const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + instance2.isDeactivated = true; + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + if (true) { + instance2.__keepAliveStorageContainer = storageContainer; + } + }; + function unmount(vnode) { + resetShapeFlag(vnode); + _unmount(vnode, instance, parentSuspense, true); + } + function pruneCache(filter) { + cache.forEach((vnode, key) => { + const name = getComponentName(vnode.type); + if (name && !filter(name)) { + pruneCacheEntry(key); + } + }); + } + function pruneCacheEntry(key) { + const cached = cache.get(key); + if (cached && (!current || !isSameVNodeType(cached, current))) { + unmount(cached); + } else if (current) { + resetShapeFlag(current); + } + cache.delete(key); + keys.delete(key); + } + watch2( + () => [props.include, props.exclude], + ([include, exclude]) => { + include && pruneCache((name) => matches(include, name)); + exclude && pruneCache((name) => !matches(exclude, name)); + }, + // prune post-render after `current` has been updated + { flush: "post", deep: true } + ); + let pendingCacheKey = null; + const cacheSubtree = () => { + if (pendingCacheKey != null) { + if (isSuspense(instance.subTree.type)) { + queuePostRenderEffect(() => { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + }, instance.subTree.suspense); + } else { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + } + } + }; + onMounted(cacheSubtree); + onUpdated(cacheSubtree); + onBeforeUnmount(() => { + cache.forEach((cached) => { + const { subTree, suspense } = instance; + const vnode = getInnerChild(subTree); + if (cached.type === vnode.type && cached.key === vnode.key) { + resetShapeFlag(vnode); + const da = vnode.component.da; + da && queuePostRenderEffect(da, suspense); + return; + } + unmount(cached); + }); + }); + return () => { + pendingCacheKey = null; + if (!slots.default) { + return current = null; + } + const children = slots.default(); + const rawVNode = children[0]; + if (children.length > 1) { + if (true) { + warn$1(`KeepAlive should contain exactly one component child.`); + } + current = null; + return children; + } else if (!isVNode(rawVNode) || !(rawVNode.shapeFlag & 4) && !(rawVNode.shapeFlag & 128)) { + current = null; + return rawVNode; + } + let vnode = getInnerChild(rawVNode); + if (vnode.type === Comment) { + current = null; + return vnode; + } + const comp = vnode.type; + const name = getComponentName( + isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : comp + ); + const { include, exclude, max } = props; + if (include && (!name || !matches(include, name)) || exclude && name && matches(exclude, name)) { + vnode.shapeFlag &= -257; + current = vnode; + return rawVNode; + } + const key = vnode.key == null ? comp : vnode.key; + const cachedVNode = cache.get(key); + if (vnode.el) { + vnode = cloneVNode(vnode); + if (rawVNode.shapeFlag & 128) { + rawVNode.ssContent = vnode; + } + } + pendingCacheKey = key; + if (cachedVNode) { + vnode.el = cachedVNode.el; + vnode.component = cachedVNode.component; + if (vnode.transition) { + setTransitionHooks(vnode, vnode.transition); + } + vnode.shapeFlag |= 512; + keys.delete(key); + keys.add(key); + } else { + keys.add(key); + if (max && keys.size > parseInt(max, 10)) { + pruneCacheEntry(keys.values().next().value); + } + } + vnode.shapeFlag |= 256; + current = vnode; + return isSuspense(rawVNode.type) ? rawVNode : vnode; + }; + } +}; +var KeepAlive = KeepAliveImpl; +function matches(pattern, name) { + if (isArray(pattern)) { + return pattern.some((p2) => matches(p2, name)); + } else if (isString(pattern)) { + return pattern.split(",").includes(name); + } else if (isRegExp(pattern)) { + pattern.lastIndex = 0; + return pattern.test(name); + } + return false; +} +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a", target); +} +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da", target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + const wrappedHook = hook.__wdc || (hook.__wdc = () => { + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + return hook(); + }); + injectHook(type, wrappedHook, target); + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } + } +} +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + const injected = injectHook( + type, + hook, + keepAliveRoot, + true + /* prepend */ + ); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} +function resetShapeFlag(vnode) { + vnode.shapeFlag &= -257; + vnode.shapeFlag &= -513; +} +function getInnerChild(vnode) { + return vnode.shapeFlag & 128 ? vnode.ssContent : vnode; +} +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + const hooks = target[type] || (target[type] = []); + const wrappedHook = hook.__weh || (hook.__weh = (...args) => { + pauseTracking(); + const reset = setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + reset(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); + } else { + hooks.push(wrappedHook); + } + return wrappedHook; + } else if (true) { + const apiName = toHandlerKey(ErrorTypeStrings$1[type].replace(/ hook$/, "")); + warn$1( + `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.` + ); + } +} +var createHook = (lifecycle) => (hook, target = currentInstance) => { + if (!isInSSRComponentSetup || lifecycle === "sp") { + injectHook(lifecycle, (...args) => hook(...args), target); + } +}; +var onBeforeMount = createHook("bm"); +var onMounted = createHook("m"); +var onBeforeUpdate = createHook( + "bu" +); +var onUpdated = createHook("u"); +var onBeforeUnmount = createHook( + "bum" +); +var onUnmounted = createHook("um"); +var onServerPrefetch = createHook( + "sp" +); +var onRenderTriggered = createHook("rtg"); +var onRenderTracked = createHook("rtc"); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec", hook, target); +} +var COMPONENTS = "components"; +var DIRECTIVES = "directives"; +function resolveComponent(name, maybeSelfReference) { + return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; +} +var NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc"); +function resolveDynamicComponent(component) { + if (isString(component)) { + return resolveAsset(COMPONENTS, component, false) || component; + } else { + return component || NULL_DYNAMIC_COMPONENT; + } +} +function resolveDirective(name) { + return resolveAsset(DIRECTIVES, name); +} +function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { + const instance = currentRenderingInstance || currentInstance; + if (instance) { + const Component = instance.type; + if (type === COMPONENTS) { + const selfName = getComponentName( + Component, + false + ); + if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) { + return Component; + } + } + const res = ( + // local registration + // check instance[type] first which is resolved for options API + resolve(instance[type] || Component[type], name) || // global registration + resolve(instance.appContext[type], name) + ); + if (!res && maybeSelfReference) { + return Component; + } + if (warnMissing && !res) { + const extra = type === COMPONENTS ? ` +If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); + } + return res; + } else if (true) { + warn$1( + `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` + ); + } +} +function resolve(registry, name) { + return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]); +} +function renderList(source, renderItem, cache, index) { + let ret; + const cached = cache && cache[index]; + const sourceIsArray = isArray(source); + if (sourceIsArray || isString(source)) { + const sourceIsReactiveArray = sourceIsArray && isReactive(source); + let needsWrap = false; + let isReadonlySource = false; + if (sourceIsReactiveArray) { + needsWrap = !isShallow(source); + isReadonlySource = isReadonly(source); + source = shallowReadArray(source); + } + ret = new Array(source.length); + for (let i = 0, l = source.length; i < l; i++) { + ret[i] = renderItem( + needsWrap ? isReadonlySource ? toReadonly(toReactive(source[i])) : toReactive(source[i]) : source[i], + i, + void 0, + cached && cached[i] + ); + } + } else if (typeof source === "number") { + if (!Number.isInteger(source)) { + warn$1(`The v-for range expect an integer value but got ${source}.`); + } + ret = new Array(source); + for (let i = 0; i < source; i++) { + ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); + } + } else if (isObject(source)) { + if (source[Symbol.iterator]) { + ret = Array.from( + source, + (item, i) => renderItem(item, i, void 0, cached && cached[i]) + ); + } else { + const keys = Object.keys(source); + ret = new Array(keys.length); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + ret[i] = renderItem(source[key], key, i, cached && cached[i]); + } + } + } else { + ret = []; + } + if (cache) { + cache[index] = ret; + } + return ret; +} +function createSlots(slots, dynamicSlots) { + for (let i = 0; i < dynamicSlots.length; i++) { + const slot = dynamicSlots[i]; + if (isArray(slot)) { + for (let j = 0; j < slot.length; j++) { + slots[slot[j].name] = slot[j].fn; + } + } else if (slot) { + slots[slot.name] = slot.key ? (...args) => { + const res = slot.fn(...args); + if (res) res.key = slot.key; + return res; + } : slot.fn; + } + } + return slots; +} +function renderSlot(slots, name, props = {}, fallback, noSlotted) { + if (currentRenderingInstance.ce || currentRenderingInstance.parent && isAsyncWrapper(currentRenderingInstance.parent) && currentRenderingInstance.parent.ce) { + if (name !== "default") props.name = name; + return openBlock(), createBlock( + Fragment, + null, + [createVNode("slot", props, fallback && fallback())], + 64 + ); + } + let slot = slots[name]; + if (slot && slot.length > 1) { + warn$1( + `SSR-optimized slot function detected in a non-SSR-optimized render function. You need to mark this component with $dynamic-slots in the parent template.` + ); + slot = () => []; + } + if (slot && slot._c) { + slot._d = false; + } + openBlock(); + const validSlotContent = slot && ensureValidVNode(slot(props)); + const slotKey = props.key || // slot content array of a dynamic conditional slot may have a branch + // key attached in the `createSlots` helper, respect that + validSlotContent && validSlotContent.key; + const rendered = createBlock( + Fragment, + { + key: (slotKey && !isSymbol(slotKey) ? slotKey : `_${name}`) + // #7256 force differentiate fallback content from actual content + (!validSlotContent && fallback ? "_fb" : "") + }, + validSlotContent || (fallback ? fallback() : []), + validSlotContent && slots._ === 1 ? 64 : -2 + ); + if (!noSlotted && rendered.scopeId) { + rendered.slotScopeIds = [rendered.scopeId + "-s"]; + } + if (slot && slot._c) { + slot._d = true; + } + return rendered; +} +function ensureValidVNode(vnodes) { + return vnodes.some((child) => { + if (!isVNode(child)) return true; + if (child.type === Comment) return false; + if (child.type === Fragment && !ensureValidVNode(child.children)) + return false; + return true; + }) ? vnodes : null; +} +function toHandlers(obj, preserveCaseIfNecessary) { + const ret = {}; + if (!isObject(obj)) { + warn$1(`v-on with no argument expects an object value.`); + return ret; + } + for (const key in obj) { + ret[preserveCaseIfNecessary && /[A-Z]/.test(key) ? `on:${key}` : toHandlerKey(key)] = obj[key]; + } + return ret; +} +var getPublicInstance = (i) => { + if (!i) return null; + if (isStatefulComponent(i)) return getComponentPublicInstance(i); + return getPublicInstance(i.parent); +}; +var publicPropertiesMap = ( + // Move PURE marker to new line to workaround compiler discarding it + // due to type annotation + extend(/* @__PURE__ */ Object.create(null), { + $: (i) => i, + $el: (i) => i.vnode.el, + $data: (i) => i.data, + $props: (i) => true ? shallowReadonly(i.props) : i.props, + $attrs: (i) => true ? shallowReadonly(i.attrs) : i.attrs, + $slots: (i) => true ? shallowReadonly(i.slots) : i.slots, + $refs: (i) => true ? shallowReadonly(i.refs) : i.refs, + $parent: (i) => getPublicInstance(i.parent), + $root: (i) => getPublicInstance(i.root), + $host: (i) => i.ce, + $emit: (i) => i.emit, + $options: (i) => __VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type, + $forceUpdate: (i) => i.f || (i.f = () => { + queueJob(i.update); + }), + $nextTick: (i) => i.n || (i.n = nextTick.bind(i.proxy)), + $watch: (i) => __VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP + }) +); +var isReservedPrefix = (key) => key === "_" || key === "$"; +var hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); +var PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + if (key === "__v_skip") { + return true; + } + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } + let normalizedProps; + if (key[0] !== "$") { + const n = accessCache[key]; + if (n !== void 0) { + switch (n) { + case 1: + return setupState[key]; + case 2: + return data[key]; + case 4: + return ctx[key]; + case 3: + return props[key]; + } + } else if (hasSetupBinding(setupState, key)) { + accessCache[key] = 1; + return setupState[key]; + } else if (data !== EMPTY_OBJ && hasOwn(data, key)) { + accessCache[key] = 2; + return data[key]; + } else if ( + // only cache other properties when instance has declared (thus stable) + // props + (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key) + ) { + accessCache[key] = 3; + return props[key]; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) { + accessCache[key] = 0; + } + } + const publicGetter = publicPropertiesMap[key]; + let cssModule, globalProperties; + if (publicGetter) { + if (key === "$attrs") { + track(instance.attrs, "get", ""); + markAttrsAccessed(); + } else if (key === "$slots") { + track(instance, "get", key); + } + return publicGetter(instance); + } else if ( + // css module (injected by vue-loader) + (cssModule = type.__cssModules) && (cssModule = cssModule[key]) + ) { + return cssModule; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if ( + // global properties + globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key) + ) { + { + return globalProperties[key]; + } + } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + warn$1( + `Property ${JSON.stringify( + key + )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` + ); + } else if (instance === currentRenderingInstance) { + warn$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } + }, + set({ _: instance }, key, value) { + const { data, setupState, ctx } = instance; + if (hasSetupBinding(setupState, key)) { + setupState[key] = value; + return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate + + diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/nginx-vue.conf b/prompto-lab-app/SF-Chain/src/main/frontend/nginx-vue.conf new file mode 100644 index 0000000..bedeb78 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/nginx-vue.conf @@ -0,0 +1,20 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # 处理Vue Router + location / { + try_files $uri $uri/ /index.html; + } + + # 代理API到后端 + location /api/ { + proxy_pass http://backend:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/package-lock.json b/prompto-lab-app/SF-Chain/src/main/frontend/package-lock.json new file mode 100644 index 0000000..ada2dcc --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/package-lock.json @@ -0,0 +1,5535 @@ +{ + "name": "poet-ui", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "poet-ui", + "version": "0.0.0", + "dependencies": { + "lodash-es": "^4.17.21", + "marked": "^16.1.0", + "pinia": "^3.0.3", + "turndown": "^7.2.0", + "vue": "^3.5.17", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/lodash-es": "^4.17.12", + "@types/node": "^22.15.32", + "@types/turndown": "^5.0.5", + "@vitejs/plugin-vue": "^5.0.0", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.5.1", + "@vue/tsconfig": "^0.7.0", + "esbuild": "^0.25.6", + "eslint": "^9.29.0", + "eslint-plugin-vue": "~10.2.0", + "jiti": "^2.4.2", + "npm-run-all2": "^8.0.4", + "prettier": "3.5.3", + "typescript": "~5.8.0", + "vite": "^5.4.10", + "vite-plugin-vue-devtools": "^7.7.7", + "vue-tsc": "^2.2.10" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", + "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.27.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", + "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", + "license": "BSD-2-Clause" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz", + "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz", + "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz", + "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz", + "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz", + "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz", + "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz", + "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz", + "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz", + "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz", + "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz", + "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz", + "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz", + "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz", + "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz", + "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz", + "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz", + "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz", + "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz", + "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz", + "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@tsconfig/node22": { + "version": "22.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.2.tgz", + "integrity": "sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "22.16.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.4.tgz", + "integrity": "sha512-PYRhNtZdm2wH/NT2k/oAJ6/f2VD2N2Dag0lGlx2vWgMSJXGNmlce5MiTQzoWAiIJtso30mjnfQCOKVH+kAQC/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/turndown": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz", + "integrity": "sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz", + "integrity": "sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/type-utils": "8.37.0", + "@typescript-eslint/utils": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.37.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.37.0.tgz", + "integrity": "sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.37.0.tgz", + "integrity": "sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.37.0", + "@typescript-eslint/types": "^8.37.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz", + "integrity": "sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz", + "integrity": "sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz", + "integrity": "sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0", + "@typescript-eslint/utils": "8.37.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.37.0.tgz", + "integrity": "sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz", + "integrity": "sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.37.0", + "@typescript-eslint/tsconfig-utils": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.37.0.tgz", + "integrity": "sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz", + "integrity": "sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.37.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.4.0.tgz", + "integrity": "sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.4.0.tgz", + "integrity": "sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.9", + "@babel/types": "^7.26.9", + "@vue/babel-helper-vue-transform-on": "1.4.0", + "@vue/babel-plugin-resolve-type": "1.4.0", + "@vue/shared": "^3.5.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.4.0.tgz", + "integrity": "sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/parser": "^7.26.9", + "@vue/compiler-sfc": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.17", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz", + "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.7" + } + }, + "node_modules/@vue/devtools-core": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.7.7.tgz", + "integrity": "sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.7", + "@vue/devtools-shared": "^7.7.7", + "mitt": "^3.0.1", + "nanoid": "^5.1.0", + "pathe": "^2.0.3", + "vite-hot-client": "^2.0.4" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", + "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.7", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", + "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", + "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" + }, + "peerDependencies": { + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.6.0.tgz", + "integrity": "sha512-UpiRY/7go4Yps4mYCjkvlIbVWmn9YvPGQDxTAlcKLphyaD77LjIu3plH4Y9zNT0GB4f3K5tMmhhtRhPOgrQ/bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.35.1", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.35.1", + "vue-eslint-parser": "^10.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz", + "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.17.tgz", + "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz", + "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.17", + "@vue/runtime-core": "3.5.17", + "@vue/shared": "3.5.17", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.17.tgz", + "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17" + }, + "peerDependencies": { + "vue": "3.5.17" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.7.0.tgz", + "integrity": "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/birpc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz", + "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.186", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.186.tgz", + "integrity": "sha512-lur7L4BFklgepaJxj4DqPk7vKbTEl0pajNlg2QjE5shefmlmBLm2HvQ7PMf1R/GvlevT/581cop33/quQcfX3A==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz", + "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/esbuild": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.8", + "@esbuild/android-arm": "0.25.8", + "@esbuild/android-arm64": "0.25.8", + "@esbuild/android-x64": "0.25.8", + "@esbuild/darwin-arm64": "0.25.8", + "@esbuild/darwin-x64": "0.25.8", + "@esbuild/freebsd-arm64": "0.25.8", + "@esbuild/freebsd-x64": "0.25.8", + "@esbuild/linux-arm": "0.25.8", + "@esbuild/linux-arm64": "0.25.8", + "@esbuild/linux-ia32": "0.25.8", + "@esbuild/linux-loong64": "0.25.8", + "@esbuild/linux-mips64el": "0.25.8", + "@esbuild/linux-ppc64": "0.25.8", + "@esbuild/linux-riscv64": "0.25.8", + "@esbuild/linux-s390x": "0.25.8", + "@esbuild/linux-x64": "0.25.8", + "@esbuild/netbsd-arm64": "0.25.8", + "@esbuild/netbsd-x64": "0.25.8", + "@esbuild/openbsd-arm64": "0.25.8", + "@esbuild/openbsd-x64": "0.25.8", + "@esbuild/openharmony-arm64": "0.25.8", + "@esbuild/sunos-x64": "0.25.8", + "@esbuild/win32-arm64": "0.25.8", + "@esbuild/win32-ia32": "0.25.8", + "@esbuild/win32-x64": "0.25.8" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", + "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.31.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", + "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.2.0.tgz", + "integrity": "sha512-tl9s+KN3z0hN2b8fV2xSs5ytGl7Esk1oSCxULLwFcdaElhZ8btYYZFrWxvh4En+czrSDtuLCeCOGa8HhEZuBdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "vue-eslint-parser": "^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", + "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/marked": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.0.tgz", + "integrity": "sha512-Me7BNa1aqrxVinDnFfvCgHh2yHvLbFvILBs899MhuBpbE5VPzpSqv7alaESfkqkgc9JNvUGH4gqwZeOzLnY8Jg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-8.0.4.tgz", + "integrity": "sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^20.5.0 || >=22.0.0", + "npm": ">= 10" + } + }, + "node_modules/npm-run-all2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm-run-all2/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/npm-run-all2/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pinia": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz", + "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.2" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-ms": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", + "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.45.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz", + "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.45.1", + "@rollup/rollup-android-arm64": "4.45.1", + "@rollup/rollup-darwin-arm64": "4.45.1", + "@rollup/rollup-darwin-x64": "4.45.1", + "@rollup/rollup-freebsd-arm64": "4.45.1", + "@rollup/rollup-freebsd-x64": "4.45.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.45.1", + "@rollup/rollup-linux-arm-musleabihf": "4.45.1", + "@rollup/rollup-linux-arm64-gnu": "4.45.1", + "@rollup/rollup-linux-arm64-musl": "4.45.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.45.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.45.1", + "@rollup/rollup-linux-riscv64-gnu": "4.45.1", + "@rollup/rollup-linux-riscv64-musl": "4.45.1", + "@rollup/rollup-linux-s390x-gnu": "4.45.1", + "@rollup/rollup-linux-x64-gnu": "4.45.1", + "@rollup/rollup-linux-x64-musl": "4.45.1", + "@rollup/rollup-win32-arm64-msvc": "4.45.1", + "@rollup/rollup-win32-ia32-msvc": "4.45.1", + "@rollup/rollup-win32-x64-msvc": "4.45.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sirv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", + "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/turndown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", + "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", + "license": "MIT", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.37.0.tgz", + "integrity": "sha512-TnbEjzkE9EmcO0Q2zM+GE8NQLItNAJpMmED1BdgoBMYNdqMhzlbqfdSwiRlAzEK2pA9UzVW0gzaaIzXWg2BjfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.37.0", + "@typescript-eslint/parser": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0", + "@typescript-eslint/utils": "8.37.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-hot-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.7.tgz", + "integrity": "sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^7.7.7", + "@vue/devtools-kit": "^7.7.7", + "@vue/devtools-shared": "^7.7.7", + "execa": "^9.5.2", + "sirv": "^3.0.1", + "vite-plugin-inspect": "0.8.9", + "vite-plugin-vue-inspector": "^5.3.1" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz", + "integrity": "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.10", + "@rollup/pluginutils": "^5.1.3", + "debug": "^4.3.7", + "error-stack-parser-es": "^0.1.5", + "fs-extra": "^11.2.0", + "open": "^10.1.0", + "perfect-debounce": "^1.0.0", + "picocolors": "^1.1.1", + "sirv": "^3.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", + "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz", + "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-sfc": "3.5.17", + "@vue/runtime-dom": "3.5.17", + "@vue/server-renderer": "3.5.17", + "@vue/shared": "3.5.17" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/package.json b/prompto-lab-app/SF-Chain/src/main/frontend/package.json new file mode 100644 index 0000000..25d5393 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/package.json @@ -0,0 +1,43 @@ +{ + "name": "poet-ui", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build", + "lint": "eslint . --fix", + "format": "prettier --write src/" + }, + "dependencies": { + "lodash-es": "^4.17.21", + "marked": "^16.1.0", + "pinia": "^3.0.3", + "turndown": "^7.2.0", + "vue": "^3.5.17", + "vue-router": "^4.5.1" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.2", + "@types/lodash-es": "^4.17.12", + "@types/node": "^22.15.32", + "@types/turndown": "^5.0.5", + "@vitejs/plugin-vue": "^5.0.0", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.5.1", + "@vue/tsconfig": "^0.7.0", + "esbuild": "^0.25.6", + "eslint": "^9.29.0", + "eslint-plugin-vue": "~10.2.0", + "jiti": "^2.4.2", + "npm-run-all2": "^8.0.4", + "prettier": "3.5.3", + "typescript": "~5.8.0", + "vite": "^5.4.10", + "vite-plugin-vue-devtools": "^7.7.7", + "vue-tsc": "^2.2.10" + } +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/public/favicon.ico b/prompto-lab-app/SF-Chain/src/main/frontend/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/prompto-lab-app/SF-Chain/src/main/frontend/public/favicon.ico differ diff --git a/prompto-lab-ui/src/assets/icons/anthropic.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/anthropic.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/anthropic.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/anthropic.svg diff --git a/prompto-lab-ui/src/assets/icons/deepseek.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/deepseek.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/deepseek.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/deepseek.svg diff --git a/prompto-lab-ui/src/assets/icons/default.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/default.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/default.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/default.svg diff --git a/prompto-lab-ui/src/assets/icons/doubao.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/doubao.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/doubao.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/doubao.svg diff --git a/prompto-lab-ui/src/assets/icons/google.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/google.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/google.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/google.svg diff --git a/prompto-lab-ui/src/assets/icons/openai.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/openai.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/openai.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/openai.svg diff --git a/prompto-lab-ui/src/assets/icons/qianwen.svg b/prompto-lab-app/SF-Chain/src/main/frontend/public/icons/qianwen.svg similarity index 100% rename from prompto-lab-ui/src/assets/icons/qianwen.svg rename to prompto-lab-app/SF-Chain/src/main/frontend/public/icons/qianwen.svg diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/App.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/App.vue new file mode 100644 index 0000000..15663fe --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/App.vue @@ -0,0 +1,544 @@ + + + + + diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/base.css b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/logo.svg b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/main.css b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/main.css new file mode 100644 index 0000000..003af53 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/assets/main.css @@ -0,0 +1,82 @@ +@import './base.css'; + +/* 重置默认样式 */ +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: #fafafa; +} + +#app { + min-height: 100vh; + width: 100%; +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #c1c1c1; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; +} + +/* 通用工具类 */ +.container { + max-width: 1400px; + margin: 0 auto; + padding: 0 20px; +} + +.text-center { + text-align: center; +} + +.mt-4 { + margin-top: 1rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.p-4 { + padding: 1rem; +} + +/* 移除了导致布局问题的样式 */ +a { + text-decoration: none; + color: #667eea; + transition: 0.3s; +} + +a:hover { + color: #764ba2; +} + +/* 确保全屏布局 */ +@media (min-width: 1024px) { + #app { + width: 100%; + max-width: none; + } +} diff --git a/prompto-lab-ui/src/components/SFChain/AICallLogViewer.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/AICallLogViewer.vue similarity index 69% rename from prompto-lab-ui/src/components/SFChain/AICallLogViewer.vue rename to prompto-lab-app/SF-Chain/src/main/frontend/src/components/AICallLogViewer.vue index df1f54c..ab7492a 100644 --- a/prompto-lab-ui/src/components/SFChain/AICallLogViewer.vue +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/AICallLogViewer.vue @@ -189,6 +189,8 @@ import { ref, onMounted, computed } from 'vue' import { aiCallLogApi } from '@/services/aiCallLogApi' import LogDetailModal from './LogDetailModal.vue' import type { AICallLogSummary } from '@/types/system' +// 导入统一的AI提供商工具函数 +import { getProviderName, getProviderIcon, getProviderFromModel } from '@/utils/aiProviders' // 状态管理 const loading = ref(false) @@ -204,11 +206,11 @@ const selectedLog = ref(null) // 计算属性 const uniqueOperations = computed(() => { - return [...new Set(logs.value.map((log:AICallLogSummary) => log.operationType))] + return [...new Set(logs.value.map(log => log.operationType))] }) const uniqueModels = computed(() => { - return [...new Set(logs.value.map((log:AICallLogSummary) => log.modelName))] + return [...new Set(logs.value.map(log => log.modelName))] }) const filteredLogs = computed(() => { @@ -217,7 +219,7 @@ const filteredLogs = computed(() => { // 搜索过滤 if (searchQuery.value) { const query = searchQuery.value.toLowerCase() - filtered = filtered.filter((log:AICallLogSummary) => + filtered = filtered.filter(log => log.callId.toLowerCase().includes(query) || log.operationType.toLowerCase().includes(query) || log.modelName.toLowerCase().includes(query) || @@ -227,21 +229,21 @@ const filteredLogs = computed(() => { // 操作类型过滤 if (filterOperation.value) { - filtered = filtered.filter((log:AICallLogSummary) => log.operationType === filterOperation.value) + filtered = filtered.filter(log => log.operationType === filterOperation.value) } // 模型过滤 if (filterModel.value) { - filtered = filtered.filter((log:AICallLogSummary) => log.modelName === filterModel.value) + filtered = filtered.filter(log => log.modelName === filterModel.value) } // 状态过滤 if (filterStatus.value) { - filtered = filtered.filter((log:AICallLogSummary) => log.status === filterStatus.value) + filtered = filtered.filter(log => log.status === filterStatus.value) } // 按时间倒序排列 - return filtered.sort((a:AICallLogSummary, b:AICallLogSummary) => new Date(b.callTime).getTime() - new Date(a.callTime).getTime()) + return filtered.sort((a, b) => new Date(b.callTime).getTime() - new Date(a.callTime).getTime()) }) const totalPages = computed(() => { @@ -254,44 +256,6 @@ const paginatedLogs = computed(() => { return filteredLogs.value.slice(start, end) }) -// 辅助函数 -const getProviderFromModel = (modelName: string): string => { - const model = modelName.toLowerCase() - if (model.includes('gpt') || model.includes('openai')) return 'openai' - if (model.includes('claude') || model.includes('anthropic')) return 'anthropic' - if (model.includes('gemini') || model.includes('google')) return 'google' - if (model.includes('deepseek')) return 'deepseek' - if (model.includes('doubao') || model.includes('豆包')) return 'doubao' - if (model.includes('qwen') || model.includes('千问') || model.includes('qianwen')) return 'qianwen' - return 'other' -} - -const getProviderName = (provider: string) => { - const names: Record = { - 'openai': 'OpenAI', - 'anthropic': 'Anthropic', - 'google': 'Google', - 'deepseek': 'DeepSeek', - 'doubao': '豆包', - 'qianwen': '千问', - 'other': '其他' - } - return names[provider] || provider -} - -const getProviderIcon = (provider: string) => { - const icons: Record = { - 'openai': '/src/assets/icons/openai.svg', - 'anthropic': '/src/assets/icons/anthropic.svg', - 'google': '/src/assets/icons/google.svg', - 'deepseek': '/src/assets/icons/deepseek.svg', - 'doubao': '/src/assets/icons/doubao.svg', - 'qianwen': '/src/assets/icons/qianwen.svg', - 'other': '/src/assets/icons/default.svg' - } - return icons[provider] || icons['other'] -} - const formatRelativeTime = (callTime: string) => { const now = Date.now() const timestamp = new Date(callTime).getTime() @@ -382,24 +346,7 @@ onMounted(() => { /* 基础样式 */ .ai-log-content { padding: 0; - background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0f0f0f 100%); - min-height: 100vh; - color: #e5e7eb; - position: relative; - overflow: hidden; -} - -.ai-log-content::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: radial-gradient(circle at 20% 20%, rgba(255, 215, 0, 0.03) 0%, transparent 50%), - radial-gradient(circle at 80% 80%, rgba(255, 215, 0, 0.02) 0%, transparent 50%); - pointer-events: none; - z-index: 0; + background: transparent; } /* 精简的页面头部 */ @@ -408,20 +355,14 @@ onMounted(() => { justify-content: space-between; align-items: center; margin-bottom: 1rem; - padding: 1.5rem 2rem 0; - position: relative; - z-index: 1; + padding: 0; } .content-header h2 { - font-size: 1.875rem; - font-weight: 700; - background: linear-gradient(135deg, #ffffff 0%, #ffd700 50%, #ffed4e 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; + font-size: 1.5rem; + font-weight: 600; + color: #2d3748; margin: 0; - text-shadow: 0 0 20px rgba(255, 215, 0, 0.3); } .header-actions { @@ -440,60 +381,51 @@ onMounted(() => { border: none; cursor: pointer; font-size: 0.875rem; - backdrop-filter: blur(10px); } .btn-secondary { - background: rgba(255, 255, 255, 0.05); - color: #e5e7eb; - border: 1px solid rgba(255, 215, 0, 0.2); + background: rgba(255, 255, 255, 0.9); + color: #4a5568; + border: 1px solid #e2e8f0; } .btn-secondary:hover:not(:disabled) { - background: rgba(255, 215, 0, 0.1); - border-color: rgba(255, 215, 0, 0.3); - box-shadow: 0 4px 12px rgba(255, 215, 0, 0.2); + background: #f7fafc; + border-color: #cbd5e0; } .btn-danger { - background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + background: #e53e3e; color: white; - border: 1px solid rgba(239, 68, 68, 0.3); } .btn-danger:hover:not(:disabled) { - background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); - box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3); + background: #c53030; } .btn:disabled { - opacity: 0.4; + opacity: 0.6; cursor: not-allowed; } .main-content { - background: rgba(255, 255, 255, 0.02); - backdrop-filter: blur(10px); - border-radius: 16px; - padding: 1.5rem 2rem; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); - border: 1px solid rgba(255, 215, 0, 0.1); - margin: 0 2rem 2rem; - position: relative; - z-index: 1; + background: rgba(255, 255, 255, 0.95); + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); + border: 1px solid rgba(255, 255, 255, 0.2); } .loading-state, .empty-state { text-align: center; padding: 3rem 2rem; - color: #9ca3af; } .loading-spinner { width: 32px; height: 32px; - border: 3px solid rgba(255, 215, 0, 0.2); - border-top: 3px solid #ffd700; + border: 3px solid #e2e8f0; + border-top: 3px solid #667eea; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 1rem; @@ -507,18 +439,16 @@ onMounted(() => { .empty-icon { font-size: 3rem; margin-bottom: 1rem; - opacity: 0.6; } .empty-state h3 { - color: #ffffff; + color: #2d3748; margin-bottom: 0.5rem; font-size: 1.125rem; - font-weight: 600; } .empty-state p { - color: #9ca3af; + color: #718096; font-size: 0.875rem; } @@ -535,7 +465,7 @@ onMounted(() => { } .log-count { - color: #9ca3af; + color: #718096; font-size: 0.875rem; font-weight: 500; } @@ -551,30 +481,23 @@ onMounted(() => { left: 0.75rem; width: 1rem; height: 1rem; - color: #ffd700; + color: #a0aec0; z-index: 1; } .search-input { padding: 0.5rem 0.75rem 0.5rem 2.25rem; - border: 1px solid rgba(255, 215, 0, 0.2); + border: 1px solid #e2e8f0; border-radius: 6px; font-size: 0.875rem; width: 200px; - transition: all 0.2s ease; - background: rgba(255, 255, 255, 0.05); - color: #e5e7eb; - backdrop-filter: blur(10px); -} - -.search-input::placeholder { - color: #9ca3af; + transition: border-color 0.2s ease; } .search-input:focus { outline: none; - border-color: #ffd700; - box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.2); + border-color: #667eea; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); } .filter-controls { @@ -585,50 +508,41 @@ onMounted(() => { .filter-select { padding: 0.5rem 0.75rem; - border: 1px solid rgba(255, 215, 0, 0.2); + border: 1px solid #e2e8f0; border-radius: 6px; font-size: 0.875rem; - background: rgba(255, 255, 255, 0.05); - color: #e5e7eb; - backdrop-filter: blur(10px); - transition: all 0.2s ease; + background: white; + transition: border-color 0.2s ease; } .filter-select:focus { outline: none; - border-color: #ffd700; - box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.2); -} - -.filter-select option { - background: #1a1a1a; - color: #e5e7eb; + border-color: #667eea; } /* 优化的表格样式 */ .table-container { - border-radius: 12px; + border-radius: 8px; overflow: hidden; - border: 1px solid rgba(255, 215, 0, 0.2); - background: rgba(255, 255, 255, 0.02); - backdrop-filter: blur(10px); + border: 1px solid #e2e8f0; + background: white; } .table-header { display: grid; grid-template-columns: 140px 100px 400px 2fr 100px 80px; gap: 0; - background: linear-gradient(135deg, rgba(255, 215, 0, 0.08) 0%, rgba(255, 215, 0, 0.04) 100%); - border-bottom: 2px solid rgba(255, 215, 0, 0.2); + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + border-bottom: 2px solid #e2e8f0; } .header-cell { padding: 1rem 0.75rem; font-weight: 600; - color: #ffd700; + color: #4a5568; font-size: 0.875rem; text-align: left; - border-right: 1px solid rgba(255, 215, 0, 0.1); + border-right: 1px solid #e2e8f0; } .header-cell:last-child { @@ -636,23 +550,22 @@ onMounted(() => { } .table-body { - background: rgba(255, 255, 255, 0.01); + background: white; } .table-row { display: grid; grid-template-columns: 140px 100px 400px 2fr 100px 80px; gap: 0; - border-bottom: 1px solid rgba(255, 215, 0, 0.1); - transition: all 0.3s ease; + border-bottom: 1px solid #f1f5f9; + transition: all 0.2s ease; position: relative; } .table-row:hover { - background: rgba(255, 215, 0, 0.05); - backdrop-filter: blur(10px); + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(255, 215, 0, 0.1); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } .table-row:last-child { @@ -660,19 +573,19 @@ onMounted(() => { } .table-row.row-failed { - background: linear-gradient(135deg, rgba(239, 68, 68, 0.1) 0%, rgba(220, 38, 38, 0.05) 100%); - border-left: 4px solid #ef4444; + background: linear-gradient(135deg, #fef5e7 0%, #fed7aa 100%); + border-left: 4px solid #f56565; } .table-row.row-failed:hover { - background: linear-gradient(135deg, rgba(239, 68, 68, 0.15) 0%, rgba(220, 38, 38, 0.1) 100%); + background: linear-gradient(135deg, #fed7aa 0%, #fbb6ce 100%); } .cell { padding: 1rem 0.75rem; display: flex; align-items: center; - border-right: 1px solid rgba(255, 215, 0, 0.05); + border-right: 1px solid #f1f5f9; min-height: 60px; } @@ -690,12 +603,12 @@ onMounted(() => { .time-relative { font-size: 0.875rem; font-weight: 500; - color: #ffffff; + color: #2d3748; } .time-full { font-size: 0.75rem; - color: #9ca3af; + color: #718096; } /* 模型列样式 */ @@ -710,20 +623,19 @@ onMounted(() => { width: 36px; height: 36px; border-radius: 8px; - background: rgba(255, 215, 0, 0.1); + background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%); display: flex; align-items: center; justify-content: center; - border: 1px solid rgba(255, 215, 0, 0.2); + border: 1px solid #e2e8f0; flex-shrink: 0; - box-shadow: 0 4px 8px rgba(255, 215, 0, 0.1); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .provider-icon { width: 20px; height: 20px; object-fit: contain; - filter: brightness(1.1); } .model-details { @@ -734,7 +646,7 @@ onMounted(() => { .model-name { font-size: 0.875rem; font-weight: 600; - color: #ffffff; + color: #2d3748; margin: 0 0 0.25rem 0; white-space: nowrap; overflow: hidden; @@ -743,7 +655,7 @@ onMounted(() => { .provider-name { font-size: 0.75rem; - color: #9ca3af; + color: #718096; font-weight: 500; } @@ -755,9 +667,9 @@ onMounted(() => { border-radius: 6px; font-size: 0.75rem; font-weight: 600; - background: rgba(59, 130, 246, 0.1); - color: #3b82f6; - border: 1px solid rgba(59, 130, 246, 0.2); + background: linear-gradient(135deg, #e6f3ff 0%, #cce7ff 100%); + color: #2b6cb0; + border: 1px solid #90cdf4; } /* 耗时列样式 */ @@ -769,27 +681,23 @@ onMounted(() => { } .duration-fast { - color: #10b981; - background: rgba(16, 185, 129, 0.1); - border: 1px solid rgba(16, 185, 129, 0.2); + color: #22543d; + background: #c6f6d5; } .duration-normal { - color: #fbbf24; - background: rgba(251, 191, 36, 0.1); - border: 1px solid rgba(251, 191, 36, 0.2); + color: #744210; + background: #faf089; } .duration-slow { - color: #ef4444; - background: rgba(239, 68, 68, 0.1); - border: 1px solid rgba(239, 68, 68, 0.2); + color: #742a2a; + background: #fed7d7; } .duration-unknown { - color: #9ca3af; - background: rgba(156, 163, 175, 0.1); - border: 1px solid rgba(156, 163, 175, 0.2); + color: #718096; + background: #edf2f7; } /* 状态列样式 */ @@ -809,21 +717,21 @@ onMounted(() => { } .status-indicator.success .status-dot { - background: #10b981; - box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2); + background: #48bb78; + box-shadow: 0 0 0 2px rgba(72, 187, 120, 0.2); } .status-indicator.success { - color: #10b981; + color: #22543d; } .status-indicator.failed .status-dot { - background: #ef4444; - box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2); + background: #f56565; + box-shadow: 0 0 0 2px rgba(245, 101, 101, 0.2); } .status-indicator.failed { - color: #ef4444; + color: #742a2a; } /* 操作列样式 */ @@ -835,24 +743,23 @@ onMounted(() => { width: 36px; height: 36px; border-radius: 8px; - border: 1px solid rgba(255, 215, 0, 0.2); - background: rgba(255, 215, 0, 0.05); - color: #9ca3af; + border: 1px solid #e2e8f0; + background: linear-gradient(135deg, #ffffff 0%, #f7fafc 100%); + color: #718096; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; - box-shadow: 0 2px 4px rgba(255, 215, 0, 0.1); - backdrop-filter: blur(10px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .action-btn:hover { - background: rgba(255, 215, 0, 0.1); - border-color: rgba(255, 215, 0, 0.4); - color: #ffd700; + background: linear-gradient(135deg, #e6f3ff 0%, #cce7ff 100%); + border-color: #90cdf4; + color: #2b6cb0; transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(255, 215, 0, 0.2); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } /* 分页样式 */ @@ -863,56 +770,40 @@ onMounted(() => { gap: 1rem; margin-top: 1.5rem; padding-top: 1rem; - border-top: 1px solid rgba(255, 215, 0, 0.2); + border-top: 1px solid #e2e8f0; } .page-btn { padding: 0.5rem 1rem; - border: 1px solid rgba(255, 215, 0, 0.2); - background: rgba(255, 255, 255, 0.05); - color: #e5e7eb; + border: 1px solid #e2e8f0; + background: white; + color: #4a5568; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; font-size: 0.875rem; - backdrop-filter: blur(10px); } .page-btn:hover:not(:disabled) { - background: rgba(255, 215, 0, 0.1); - border-color: rgba(255, 215, 0, 0.3); - color: #ffd700; + background: #f7fafc; + border-color: #cbd5e0; } .page-btn:disabled { - opacity: 0.4; + opacity: 0.5; cursor: not-allowed; } .page-info { - color: #9ca3af; + color: #718096; font-size: 0.875rem; - font-weight: 500; -} - -/* 工具类 */ -.w-4 { - width: 1rem; -} - -.h-4 { - height: 1rem; -} - -.animate-spin { - animation: spin 1s linear infinite; } /* 响应式设计 */ @media (max-width: 1200px) { .table-header, .table-row { - grid-template-columns: 120px 90px 300px 2fr 90px 70px; + grid-template-columns: 120px 80px 250px 2fr 80px 60px; } } @@ -923,76 +814,42 @@ onMounted(() => { align-items: flex-start; } - .header-info { - flex-direction: column; - gap: 0.75rem; - align-items: flex-start; - } - - .search-input { + .header-actions { width: 100%; + justify-content: flex-end; } - .filter-controls { - flex-wrap: wrap; - } - - .table-header { - display: none; + .list-header { + flex-direction: column; + gap: 1rem; } - .table-row { - display: flex; + .header-info { flex-direction: column; gap: 0.75rem; - padding: 1rem; - border: 1px solid rgba(255, 215, 0, 0.2); - border-radius: 8px; - margin-bottom: 0.75rem; - background: rgba(255, 255, 255, 0.02); - } - - .table-body { - padding: 0.75rem; - } - - .cell { - padding: 0; - border: none; - min-height: auto; - } - - .model-info { - width: 100%; - } - - .main-content { - margin: 0 1rem 1rem; - padding: 1rem; + align-items: flex-start; } - .content-header { - padding: 1rem; + .filter-controls { + flex-wrap: wrap; + gap: 0.5rem; } -} -@media (max-width: 480px) { - .header-actions { - flex-direction: column; - width: 100%; + .table-header, + .table-row { + grid-template-columns: 100px 80px 120px 1fr 80px 60px; } - .btn { - justify-content: center; + .search-input { + width: 150px; } - .filter-controls { - flex-direction: column; - width: 100%; + .model-name { + font-size: 0.75rem; } - .filter-select { - width: 100%; + .provider-name { + font-size: 0.65rem; } } diff --git a/prompto-lab-ui/src/components/Chat/AiNodeConfig.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/AiNodeConfig.vue similarity index 79% rename from prompto-lab-ui/src/components/Chat/AiNodeConfig.vue rename to prompto-lab-app/SF-Chain/src/main/frontend/src/components/AiNodeConfig.vue index 13c931c..d25a6bb 100644 --- a/prompto-lab-ui/src/components/Chat/AiNodeConfig.vue +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/AiNodeConfig.vue @@ -112,7 +112,7 @@ :class="{ 'configured': operation.modelName, 'disabled': !operation.enabled, - 'testing': testing === String(operationType) + 'testing': testing === operationType }" > @@ -147,7 +147,7 @@ :class="{ 'has-value': operation.modelName }" > - + @@ -183,10 +183,10 @@ v-if="operation.modelName" @click="testOperation(String(operationType))" class="action-btn test large" - :disabled="testing === String(operationType)" - :title="testing === String(operationType) ? '测试中...' : '测试操作'" + :disabled="testing === operationType" + :title="testing === operationType ? '测试中...' : '测试操作'" > - + @@ -226,7 +226,7 @@
- + + +
@@ -384,6 +382,16 @@ import { ref, reactive, onMounted, computed } from 'vue' import { aiModelApi } from '@/services/aiModelApi' import type { ModelConfigData, ModelsResponse } from '@/types/system' +// 导入增强的AI提供商工具函数 +import { + getProviderName, + getProviderIcon, + getProviderOrder, + getAllProviders, + getProvidersByCategory, + getCategoryName, + getProviderDefaultConfig +} from '@/utils/aiProviders' // 状态管理 const loading = ref(false) @@ -449,10 +457,8 @@ const sortedProviderStats = computed(() => { return [] } - // 定义提供商顺序(与getProviderIcon中的顺序一致) - const providerOrder = ['openai', 'anthropic', 'google', 'deepseek', 'doubao', 'qianwen', 'other'] - const stats = [] + const providerOrder = getProviderOrder() // 按照预定义顺序添加存在的提供商 for (const provider of providerOrder) { @@ -474,33 +480,12 @@ const sortedProviderStats = computed(() => { return stats }) -// 辅助函数 -const getProviderName = (provider: string) => { - const names: Record = { - 'openai': 'OpenAI', - 'anthropic': 'Anthropic', - 'google': 'Google', - 'deepseek': 'DeepSeek', - 'doubao': '豆包', - 'qianwen': '千问', - 'other': '其他' - } - return names[provider] || provider -} - -const getProviderIcon = (provider: string) => { - const icons: Record = { - 'openai': '/src/assets/icons/openai.svg', - 'anthropic': '/src/assets/icons/anthropic.svg', - 'google': '/src/assets/icons/google.svg', - 'deepseek': '/src/assets/icons/deepseek.svg', - 'doubao': '/src/assets/icons/doubao.svg', - 'qianwen': '/src/assets/icons/qianwen.svg', - 'other': '/src/assets/icons/default.svg' - } - return icons[provider] || icons['other'] -} +// 计算属性 - 按分类分组的提供商 +const providersByCategory = computed(() => { + return getProvidersByCategory() +}) +// 辅助函数 const getModelIcon = (provider?: string) => { return getProviderIcon(provider || 'other') } @@ -518,6 +503,27 @@ const selectProvider = (provider: string) => { searchQuery.value = '' } +// 提供商变更时的处理 +const onProviderChange = () => { + const defaultConfig = getProviderDefaultConfig(modelForm.provider) + if (defaultConfig) { + // 只在字段为空时应用默认值,避免覆盖用户已输入的内容 + if (!modelForm.baseUrl) { + modelForm.baseUrl = defaultConfig.baseUrl || '' + } + if (!modelForm.defaultMaxTokens) { + modelForm.defaultMaxTokens = defaultConfig.maxTokens || 4096 + } + if (!modelForm.defaultTemperature) { + modelForm.defaultTemperature = defaultConfig.temperature || 0.7 + } + // 应用支持特性的默认值 + modelForm.supportStream = defaultConfig.supportStream ?? true + modelForm.supportJsonOutput = defaultConfig.supportJsonOutput ?? true + modelForm.supportThinking = defaultConfig.supportThinking ?? false + } +} + // 复制到剪贴板 const copyToClipboard = async (text: string) => { try { @@ -668,7 +674,7 @@ onMounted(() => { - diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/components/HeaderBar.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/HeaderBar.vue new file mode 100644 index 0000000..1c965d8 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/HeaderBar.vue @@ -0,0 +1,564 @@ + + + + + diff --git a/prompto-lab-ui/src/components/SFChain/JsonViewer.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/JsonViewer.vue similarity index 90% rename from prompto-lab-ui/src/components/SFChain/JsonViewer.vue rename to prompto-lab-app/SF-Chain/src/main/frontend/src/components/JsonViewer.vue index 88cc099..816cceb 100644 --- a/prompto-lab-ui/src/components/SFChain/JsonViewer.vue +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/JsonViewer.vue @@ -248,10 +248,10 @@ const countItems = (obj: JsonValue): number => { if (obj === null || obj === undefined || typeof obj !== 'object') return 1 if (Array.isArray(obj)) { - return obj.reduce((sum:number, item) => sum + countItems(item), 0) + return obj.reduce((sum, item) => sum + countItems(item), 0) } - return Object.values(obj as JsonObject).reduce((sum:number, value) => sum + countItems(value), 0) + return Object.values(obj as JsonObject).reduce((sum, value) => sum + countItems(value), 0) } // 事件处理 @@ -292,10 +292,10 @@ nextTick(() => { \ No newline at end of file + diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/components/Toast.vue b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/Toast.vue new file mode 100644 index 0000000..481e87a --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/components/Toast.vue @@ -0,0 +1,546 @@ + + + + + diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/main.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/main.ts new file mode 100644 index 0000000..9c83fc5 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/main.ts @@ -0,0 +1,22 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' +import { apiClient } from './services/apiUtils' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +// 初始化API配置 +apiClient.initialize().then(() => { + app.mount('#app') +}).catch(error => { + console.error('Failed to initialize API config:', error) + // 即使配置失败也要启动应用,使用默认配置 + app.mount('#app') +}) diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/router/index.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/router/index.ts new file mode 100644 index 0000000..fec90c5 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/router/index.ts @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' +import App from '../App.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: App + } + ] +}) + +export default router diff --git a/prompto-lab-ui/src/services/aiCallLogApi.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiCallLogApi.ts similarity index 67% rename from prompto-lab-ui/src/services/aiCallLogApi.ts rename to prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiCallLogApi.ts index d15085a..6d4751c 100644 --- a/prompto-lab-ui/src/services/aiCallLogApi.ts +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiCallLogApi.ts @@ -5,7 +5,7 @@ import type { AICallLogSummary, AICallLog, LogStatistics, ApiResponse } from '@/ export const aiCallLogApi = { // 获取所有日志摘要(轻量级) async getAllLogSummaries(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs`, { method: 'GET', requireAuth: true }) @@ -13,7 +13,7 @@ export const aiCallLogApi = { // 根据调用ID获取完整日志详情 async getFullLog(callId: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs/${encodeURIComponent(callId)}`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs/${encodeURIComponent(callId)}`, { method: 'GET', requireAuth: true }) @@ -21,7 +21,7 @@ export const aiCallLogApi = { // 根据操作类型获取日志摘要 async getLogSummariesByOperation(operationType: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs/operation/${encodeURIComponent(operationType)}`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs/operation/${encodeURIComponent(operationType)}`, { method: 'GET', requireAuth: true }) @@ -29,7 +29,7 @@ export const aiCallLogApi = { // 根据模型名称获取日志摘要 async getLogSummariesByModel(modelName: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs/model/${encodeURIComponent(modelName)}`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs/model/${encodeURIComponent(modelName)}`, { method: 'GET', requireAuth: true }) @@ -37,7 +37,7 @@ export const aiCallLogApi = { // 获取统计信息 async getStatistics(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs/statistics`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs/statistics`, { method: 'GET', requireAuth: true }) @@ -45,7 +45,7 @@ export const aiCallLogApi = { // 清空所有日志 async clearLogs(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/ai-logs`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/ai-logs`, { method: 'DELETE', requireAuth: true }) diff --git a/prompto-lab-ui/src/services/aiModelApi.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiModelApi.ts similarity index 76% rename from prompto-lab-ui/src/services/aiModelApi.ts rename to prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiModelApi.ts index 05e5e6b..54b6ce4 100644 --- a/prompto-lab-ui/src/services/aiModelApi.ts +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiModelApi.ts @@ -5,7 +5,7 @@ import type { ModelConfigData, ApiResponse, ModelsResponse, TestConnectionRespon export const aiModelApi = { // 获取所有模型配置 async getAllModels(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/models/list`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/models/list`, { method: 'GET', requireAuth: true }) @@ -13,7 +13,7 @@ export const aiModelApi = { // 获取单个模型配置 - 改为POST请求 async getModel(modelName: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/models/get`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/models/get`, { method: 'POST', body: JSON.stringify({ modelName }), requireAuth: true @@ -22,7 +22,7 @@ export const aiModelApi = { // 保存模型配置(创建或更新) async saveModel(modelName: string, config: ModelConfigData): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/models/save`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/models/save`, { method: 'POST', body: JSON.stringify({ ...config, modelName }), requireAuth: true @@ -31,7 +31,7 @@ export const aiModelApi = { // 删除模型配置 - 改为POST请求 async deleteModel(modelName: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/models/delete`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/models/delete`, { method: 'POST', body: JSON.stringify({ modelName }), requireAuth: true @@ -40,7 +40,7 @@ export const aiModelApi = { // 测试模型连接 - 改为POST请求 async testModel(modelName: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/models/test`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/models/test`, { method: 'POST', body: JSON.stringify({ modelName }), requireAuth: true diff --git a/prompto-lab-ui/src/services/aiOperationApi.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiOperationApi.ts similarity index 79% rename from prompto-lab-ui/src/services/aiOperationApi.ts rename to prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiOperationApi.ts index 0b8172b..cbd0b83 100644 --- a/prompto-lab-ui/src/services/aiOperationApi.ts +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/aiOperationApi.ts @@ -5,7 +5,7 @@ import type { OperationConfigData, OperationsResponse, OperationDetailResponse, export const aiOperationApi = { // 获取所有操作配置 async getAllOperations(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/operations`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/operations`, { method: 'GET', requireAuth: true }) @@ -13,7 +13,7 @@ export const aiOperationApi = { // 获取单个操作配置 - 改为POST请求 async getOperation(operationType: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/operations/get`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/operations/get`, { method: 'POST', body: JSON.stringify({ operationType }), requireAuth: true @@ -28,7 +28,7 @@ export const aiOperationApi = { operationType: operationType } - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/operations/save`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/operations/save`, { method: 'POST', body: JSON.stringify(configWithType), requireAuth: true @@ -37,7 +37,7 @@ export const aiOperationApi = { // 设置单个操作模型映射 - 改为请求体参数 async setOperationMapping(operationType: string, modelName: string): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/operations/mapping`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/operations/mapping`, { method: 'POST', body: JSON.stringify({ operationType, modelName }), requireAuth: true @@ -46,7 +46,7 @@ export const aiOperationApi = { // 批量设置操作模型映射 async setOperationMappings(mappings: Record): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/operations/mappings`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/operations/mappings`, { method: 'POST', body: JSON.stringify({ mappings }), requireAuth: true diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiConfig.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiConfig.ts new file mode 100644 index 0000000..5371e7c --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiConfig.ts @@ -0,0 +1,65 @@ +// API配置 +interface ApiConfig { + baseUrl: string; + endpoints: { + AI_MODELS: string; + AI_OPERATIONS: string; + AI_CALL_LOGS: string; + AI_SYSTEM: string; + }; +} + +let apiConfig: ApiConfig | null = null; + +// 动态获取API配置 +export async function getApiConfig(): Promise { + if (apiConfig) { + return apiConfig; + } + + try { + // 在生产环境中,从当前域名获取配置 + const configUrl = import.meta.env.DEV + ? 'http://localhost:5001/api/sf-chain/config/api-info' + : '/sf-chain/config/api-info'; + + const response = await fetch(configUrl); + const config = await response.json(); + + apiConfig = { + baseUrl: config.baseUrl || '', + endpoints: config.endpoints || { + AI_MODELS: '/sf-chain/models', + AI_OPERATIONS: '/sf-chain/operations', + AI_CALL_LOGS: '/sf-chain/call-logs', + AI_SYSTEM: '/sf-chain/system' + } + }; + + return apiConfig; + } catch (error) { + console.warn('Failed to fetch API config, using defaults:', error); + // 降级到默认配置 + apiConfig = { + baseUrl: import.meta.env.DEV ? 'http://localhost:5001/api' : '', + endpoints: { + AI_MODELS: '/sf-chain/models', + AI_OPERATIONS: '/sf-chain/operations', + AI_CALL_LOGS: '/sf-chain/call-logs', + AI_SYSTEM: '/sf-chain/system' + } + }; + return apiConfig; + } +} + +// 兼容性导出 +export const API_CONFIG = { + BASE_URL: '', // 将在运行时动态设置 + ENDPOINTS: { + AI_MODELS: '/sf-chain/models', + AI_OPERATIONS: '/sf-chain/operations', + AI_CALL_LOGS: '/sf-chain/call-logs', + AI_SYSTEM: '/sf-chain/system' + } +}; diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiUtils.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiUtils.ts new file mode 100644 index 0000000..8084462 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/apiUtils.ts @@ -0,0 +1,263 @@ +import { toast } from '@/utils/toast' +import { getApiConfig } from './apiConfig'; + +// API请求工具函数 +export interface RequestOptions { + method?: string + headers?: Record + body?: string + signal?: AbortSignal + requireAuth?: boolean + isAIRequest?: boolean +} + +// 获取存储的token +export function getAuthToken(): string | null { + return localStorage.getItem('token') +} + +// 设置token +export function setAuthToken(token: string): void { + localStorage.setItem('token', token) +} + +// 清除认证信息 +function clearAuthData() { + localStorage.removeItem('token') + localStorage.removeItem('userInfo') +} + +// 处理认证失败 +function handleAuthFailure() { + clearAuthData() + toast.error({ + title: '认证失败', + message: '请检查您的token是否正确', + duration: 4000 + }) +} + +// 处理需要登录 +function handleRequireLogin() { + toast.error({ + title: '需要认证', + message: '请在页面顶部输入有效的token', + duration: 4000 + }) +} + +// 统一的请求函数 +export async function apiRequest(url: string, options: RequestOptions = {}): Promise { + const { + method = 'GET', + headers = {}, + body, + signal, + requireAuth = true, + isAIRequest = false + } = options + + const requestHeaders: Record = { + 'Content-Type': 'application/json', + ...headers + } + + // 判断是否是AI请求 + const isAI = isAIRequest || url.includes('/sf-chain/') + + if (isAI || requireAuth) { + // AI接口和普通接口都统一使用Authorization token + const token = getAuthToken() + if (token) { + requestHeaders['Authorization'] = `${token}` + } else { + handleRequireLogin() + throw new Error('未提供认证token') + } + + if (isAI) { + console.log('🔍 AI请求调试信息:') + console.log('URL:', url) + console.log('Authorization Token:', token) + console.log('请求头:', requestHeaders) + } + } + + try { + console.log('📤 发送请求:', { url, method, headers: requestHeaders }) + const response = await fetch(url, { + method, + headers: requestHeaders, + body, + signal + }) + + if (response.status === 401) { + if (isAI) { + toast.error({ + title: 'AI接口认证失败', + message: '缺少Authorization请求头', + duration: 4000 + }) + } else { + handleAuthFailure() + } + throw new Error('认证失败') + } + + if (response.status === 403) { + if (isAI) { + toast.error({ + title: 'AI接口权限不足', + message: 'Authorization验证失败', + duration: 4000 + }) + } else { + toast.error({ + title: '权限不足', + message: '您没有权限执行此操作', + duration: 4000 + }) + } + throw new Error('权限不足') + } + + if (response.status === 404) { + toast.error({ + title: '资源不存在', + message: '请求的资源不存在或已被删除', + duration: 3000 + }) + throw new Error('资源不存在') + } + + if (response.status >= 500) { + toast.error({ + title: '服务器错误', + message: '服务器暂时无法处理您的请求,请稍后重试', + duration: 5000, + closable: true + }) + throw new Error('服务器错误') + } + + return response + } catch (error: unknown) { + const err = error as Error + if (err.name === 'TypeError' && err.message.includes('fetch')) { + toast.error({ + title: '网络连接失败', + message: '无法连接到服务器,请检查网络连接', + duration: 5000, + closable: true + }) + } else if (err.name === 'AbortError') { + console.log('请求已取消') + } else if (!err.message.includes('认证失败') && + !err.message.includes('权限不足') && + !err.message.includes('资源不存在') && + !err.message.includes('未提供认证token')) { + toast.error({ + title: '请求失败', + message: err.message || '请求处理失败,请稍后重试', + duration: 4000 + }) + } + throw error + } +} + +// 便捷的JSON请求函数 +export async function apiJsonRequest( + url: string, + options: RequestOptions = {} +): Promise { + const response = await apiRequest(url, options) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + try { + return await response.json() + } catch { + toast.error({ + title: '数据解析失败', + message: '服务器返回的数据格式有误', + duration: 3000 + }) + throw new Error('数据解析失败') + } +} + +// AI接口专用请求函数 +export async function aiApiRequest( + url: string, + options: RequestOptions = {} +): Promise { + return apiJsonRequest(url, { ...options, isAIRequest: true }) +} + +export class ApiClient { + private static instance: ApiClient; + private baseUrl: string = ''; + + private constructor() {} + + public static getInstance(): ApiClient { + if (!ApiClient.instance) { + ApiClient.instance = new ApiClient(); + } + return ApiClient.instance; + } + + public async initialize(): Promise { + const config = await getApiConfig(); + this.baseUrl = config.baseUrl; + } + + public async request(endpoint: string, options: RequestInit = {}): Promise { + if (!this.baseUrl) { + await this.initialize(); + } + + const url = `${this.baseUrl}${endpoint}`; + const response = await fetch(url, { + headers: { + 'Content-Type': 'application/json', + ...options.headers, + }, + ...options, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return response.json(); + } + + public async get(endpoint: string): Promise { + return this.request(endpoint, { method: 'GET' }); + } + + public async post(endpoint: string, data?: any): Promise { + return this.request(endpoint, { + method: 'POST', + body: data ? JSON.stringify(data) : undefined, + }); + } + + public async put(endpoint: string, data?: any): Promise { + return this.request(endpoint, { + method: 'PUT', + body: data ? JSON.stringify(data) : undefined, + }); + } + + public async delete(endpoint: string): Promise { + return this.request(endpoint, { method: 'DELETE' }); + } +} + +export const apiClient = ApiClient.getInstance(); diff --git a/prompto-lab-ui/src/services/systemApi.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/systemApi.ts similarity index 69% rename from prompto-lab-ui/src/services/systemApi.ts rename to prompto-lab-app/SF-Chain/src/main/frontend/src/services/systemApi.ts index c5eea45..c28f5f1 100644 --- a/prompto-lab-ui/src/services/systemApi.ts +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/services/systemApi.ts @@ -5,7 +5,7 @@ import type { SystemOverview, ApiResponse } from '@/types/system' export const systemApi = { // 获取系统概览信息 async getSystemOverview(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/system/overview`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/system/overview`, { method: 'GET', requireAuth: true }) @@ -13,7 +13,7 @@ export const systemApi = { // 创建系统配置备份 async createBackup(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/system/backup`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/system/backup`, { method: 'POST', requireAuth: true }) @@ -21,7 +21,7 @@ export const systemApi = { // 刷新系统配置 async refreshSystem(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/system/refresh`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/system/refresh`, { method: 'POST', requireAuth: true }) @@ -29,9 +29,9 @@ export const systemApi = { // 重置系统配置 async resetSystem(): Promise { - return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf/api/system/reset`, { + return apiJsonRequest(`${API_CONFIG.BASE_URL}/sf-chain/system/reset`, { method: 'POST', requireAuth: true }) } -} \ No newline at end of file +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/types/system.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/types/system.ts new file mode 100644 index 0000000..ee0d08c --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/types/system.ts @@ -0,0 +1,127 @@ +export interface SystemOverview { + totalModels: number + enabledModels: number + totalOperations: number + enabledOperations: number // 添加这个字段 + configuredOperations: number + lastUpdate: number +} + +export interface ApiResponse { + success: boolean + message: string + data?: T + timestamp?: number + code?: number +} + +export interface ModelConfigData { + modelName: string + baseUrl: string + apiKey: string + defaultMaxTokens?: number + defaultTemperature?: number + supportStream?: boolean + supportJsonOutput?: boolean + supportThinking?: boolean + additionalHeaders?: Record + description?: string + provider?: string + enabled?: boolean +} + +export interface ApiResponse { + success: boolean + message: string + data?: T + modelName?: string + validated?: boolean + error?: string +} + +export interface ModelsResponse { + models: Record + groupedByProvider: Record + total: number +} + +export interface TestConnectionResponse { + success: boolean + message: string + modelName: string +} + +export interface ModelListResponse { + models: Record + groupedByProvider: Record + total: number +} + +export interface OperationConfigData { + operationType: string + description?: string + enabled?: boolean + maxTokens?: number + temperature?: number + timeout?: number + retryCount?: number + jsonOutput?: boolean + streamOutput?: boolean + thinkingMode?: boolean + promptPrefix?: string + promptSuffix?: string + systemPrompt?: string + outputFormat?: string + customParams?: Record + modelName?: string +} + +export interface OperationsResponse { + mappings: Record + configs: Record + totalOperations: number + configuredOperations: number +} + +export interface OperationDetailResponse { + operation: OperationConfigData + associatedModel?: ModelConfigData +} + +// AI调用日志相关类型定义 +// 更新 AICallLogSummary 接口 +export interface AICallLogSummary { + callId: string + operationType: string + modelName: string + callTime: string // 后端返回LocalDateTime转换为字符串 + duration: number + status: string // 后端返回CallStatus枚举转换为字符串 + errorMessage: string | null + frequency: number + lastAccessTime: string + requestParams?: { + maxTokens: number + temperature: number + jsonOutput: boolean + thinking: boolean + } +} + +// 新增 AICallLog 接口 +export interface AICallLog extends AICallLogSummary { + input?: Record + prompt?: string + rawResponse?: string + output?: Record +} + +export interface LogStatistics { + totalCalls: number + successfulCalls: number + failedCalls: number + totalTokensUsed: number + averageResponseTime: number + callsByOperation: Record + callsByModel: Record +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/aiProviders.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/aiProviders.ts new file mode 100644 index 0000000..a275b5c --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/aiProviders.ts @@ -0,0 +1,215 @@ +// AI提供商相关工具函数 +export interface AIProvider { + key: string + name: string + icon: string + // 新增:用于表单显示的配置 + displayOrder: number + category?: string + description?: string + // 新增:默认配置建议 + defaultConfig?: { + baseUrl?: string + maxTokens?: number + temperature?: number + supportStream?: boolean + supportJsonOutput?: boolean + supportThinking?: boolean + } +} + +// AI提供商配置 - 增强版 +const AI_PROVIDERS: Record = { + openai: { + key: 'openai', + name: 'OpenAI', + icon: '/icons/openai.svg', + displayOrder: 1, + category: 'commercial', + description: 'OpenAI GPT系列模型', + defaultConfig: { + baseUrl: 'https://api.openai.com/v1', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: false + } + }, + anthropic: { + key: 'anthropic', + name: 'Anthropic', + icon: '/icons/anthropic.svg', + displayOrder: 2, + category: 'commercial', + description: 'Anthropic Claude系列模型', + defaultConfig: { + baseUrl: 'https://api.anthropic.com/v1', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: true + } + }, + google: { + key: 'google', + name: 'Google', + icon: '/icons/google.svg', + displayOrder: 3, + category: 'commercial', + description: 'Google Gemini系列模型', + defaultConfig: { + baseUrl: 'https://generativelanguage.googleapis.com/v1', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: false + } + }, + deepseek: { + key: 'deepseek', + name: 'DeepSeek', + icon: '/icons/deepseek.svg', + displayOrder: 4, + category: 'domestic', + description: 'DeepSeek系列模型', + defaultConfig: { + baseUrl: 'https://api.deepseek.com/v1', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: true + } + }, + doubao: { + key: 'doubao', + name: '豆包', + icon: '/icons/doubao.svg', + displayOrder: 5, + category: 'domestic', + description: '字节跳动豆包系列模型', + defaultConfig: { + baseUrl: 'https://ark.cn-beijing.volces.com/api/v3', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: false + } + }, + qianwen: { + key: 'qianwen', + name: '千问', + icon: '/icons/qianwen.svg', + displayOrder: 6, + category: 'domestic', + description: '阿里云千问系列模型', + defaultConfig: { + baseUrl: 'https://dashscope.aliyuncs.com/api/v1', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: true, + supportThinking: false + } + }, + other: { + key: 'other', + name: '其他', + icon: '/icons/default.svg', + displayOrder: 999, + category: 'custom', + description: '自定义或其他提供商', + defaultConfig: { + baseUrl: '', + maxTokens: 4096, + temperature: 0.7, + supportStream: true, + supportJsonOutput: false, + supportThinking: false + } + } +} + +/** + * 获取提供商名称 + */ +export const getProviderName = (provider: string): string => { + return AI_PROVIDERS[provider]?.name || AI_PROVIDERS.other.name +} + +/** + * 获取提供商图标路径 + */ +export const getProviderIcon = (provider: string): string => { + return AI_PROVIDERS[provider]?.icon || AI_PROVIDERS.other.icon +} + +/** + * 根据模型名称推断提供商 + */ +export const getProviderFromModel = (modelName: string): string => { + const model = modelName.toLowerCase() + if (model.includes('gpt') || model.includes('openai')) return 'openai' + if (model.includes('claude') || model.includes('anthropic')) return 'anthropic' + if (model.includes('gemini') || model.includes('google')) return 'google' + if (model.includes('deepseek')) return 'deepseek' + if (model.includes('doubao') || model.includes('豆包')) return 'doubao' + if (model.includes('qwen') || model.includes('千问') || model.includes('qianwen')) return 'qianwen' + return 'other' +} + +/** + * 获取所有提供商列表(按显示顺序排序) + */ +export const getAllProviders = (): AIProvider[] => { + return Object.values(AI_PROVIDERS).sort((a, b) => a.displayOrder - b.displayOrder) +} + +/** + * 按分类获取提供商 + */ +export const getProvidersByCategory = (): Record => { + const categories: Record = {} + const providers = getAllProviders() + + providers.forEach(provider => { + const category = provider.category || 'other' + if (!categories[category]) { + categories[category] = [] + } + categories[category].push(provider) + }) + + return categories +} + +/** + * 获取提供商的默认配置 + */ +export const getProviderDefaultConfig = (provider: string) => { + return AI_PROVIDERS[provider]?.defaultConfig || AI_PROVIDERS.other.defaultConfig +} + +/** + * 获取分类显示名称 + */ +export const getCategoryName = (category: string): string => { + const categoryNames: Record = { + commercial: '商业模型', + domestic: '国产模型', + custom: '自定义', + other: '其他' + } + return categoryNames[category] || category +} + +/** + * 提供商顺序(用于排序显示) + */ +export const getProviderOrder = (): string[] => { + return getAllProviders().map(provider => provider.key) +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/toast.ts b/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/toast.ts new file mode 100644 index 0000000..3d764f2 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/src/utils/toast.ts @@ -0,0 +1,189 @@ +import { createApp, type App } from 'vue' +import Toast from '@/components/Toast.vue' + +interface ToastOptions { + type?: 'success' | 'error' | 'warning' | 'info' + title?: string + message: string + duration?: number + closable?: boolean + showProgress?: boolean + position?: 'top' | 'center' | 'bottom' + offset?: number +} + +// 预设的停留时间配置 +const DURATION_PRESETS = { + success: 3000, + error: 6000, + warning: 4000, + info: 3000, + short: 2000, + medium: 4000, + long: 6000, + persistent: 0 // 不自动关闭 +} + +class ToastManager { + private toasts: { app: App; container: HTMLElement; id: string }[] = [] + private toastCounter = 0 + + private show(options: ToastOptions) { + const id = `toast-${++this.toastCounter}` + const container = document.createElement('div') + + // 计算位置偏移 + const offset = this.calculateOffset(options.position || 'top') + + const app = createApp(Toast, { + ...options, + id, + offset, + onClose: () => { + this.remove(app) + } + }) + + app.mount(container) + this.toasts.push({ app, container, id }) + + return app + } + + private calculateOffset(position: string): number { + const samePositionToasts = this.toasts.filter(toast => { + // 这里需要从toast实例中获取position,简化处理 + return true + }) + return samePositionToasts.length * 80 // 每个toast间隔80px + } + + private remove(targetApp: App) { + const index = this.toasts.findIndex(({ app }) => app === targetApp) + if (index > -1) { + const { app, container } = this.toasts[index] + this.toasts.splice(index, 1) + app.unmount() + if (container.parentNode) { + container.parentNode.removeChild(container) + } + // 重新计算其他toast的位置 + this.updatePositions() + } + } + + private updatePositions() { + // 更新剩余toast的位置 + this.toasts.forEach((toast, index) => { + // 这里可以通过expose的方法更新位置 + }) + } + + // 支持预设时长 + success(messageOrOptions: string | ToastOptions, title?: string, options?: Partial) { + if (typeof messageOrOptions === 'string') { + return this.show({ + type: 'success', + title: title || '成功', + message: messageOrOptions, + duration: DURATION_PRESETS.success, + ...options + }) + } else { + return this.show({ + type: 'success', + title: messageOrOptions.title || '成功', + duration: DURATION_PRESETS.success, + ...messageOrOptions + }) + } + } + + error(messageOrOptions: string | ToastOptions, title?: string, options?: Partial) { + if (typeof messageOrOptions === 'string') { + return this.show({ + type: 'error', + title: title || '错误', + message: messageOrOptions, + duration: DURATION_PRESETS.error, + ...options + }) + } else { + return this.show({ + type: 'error', + title: messageOrOptions.title || '错误', + duration: DURATION_PRESETS.error, + ...messageOrOptions + }) + } + } + + warning(messageOrOptions: string | ToastOptions, title?: string, options?: Partial) { + if (typeof messageOrOptions === 'string') { + return this.show({ + type: 'warning', + title: title || '警告', + message: messageOrOptions, + duration: DURATION_PRESETS.warning, + ...options + }) + } else { + return this.show({ + type: 'warning', + title: messageOrOptions.title || '警告', + duration: DURATION_PRESETS.warning, + ...messageOrOptions + }) + } + } + + info(messageOrOptions: string | ToastOptions, title?: string, options?: Partial) { + if (typeof messageOrOptions === 'string') { + return this.show({ + type: 'info', + title: title || '提示', + message: messageOrOptions, + duration: DURATION_PRESETS.info, + ...options + }) + } else { + return this.show({ + type: 'info', + title: messageOrOptions.title || '提示', + duration: DURATION_PRESETS.info, + ...messageOrOptions + }) + } + } + + // 新增便捷方法 + quick(message: string, type: 'success' | 'error' | 'warning' | 'info' = 'info') { + return this.show({ + type, + message, + duration: DURATION_PRESETS.short, + showProgress: false, + closable: false + }) + } + + persistent(message: string, title?: string, type: 'success' | 'error' | 'warning' | 'info' = 'info') { + return this.show({ + type, + title, + message, + duration: 0, + closable: true + }) + } + + clear() { + this.toasts.forEach(({ app }) => { + this.remove(app) + }) + } +} + +export const toast = new ToastManager() +export type { ToastOptions } +export { DURATION_PRESETS } diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.app.json b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.app.json new file mode 100644 index 0000000..913b8f2 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.json b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.node.json b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.node.json new file mode 100644 index 0000000..a83dfc9 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/prompto-lab-app/SF-Chain/src/main/frontend/vite.config.ts b/prompto-lab-app/SF-Chain/src/main/frontend/vite.config.ts new file mode 100644 index 0000000..4217010 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/frontend/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, +}) diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/annotation/AIOp.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/annotation/AIOp.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/annotation/AIOp.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/annotation/AIOp.java index 71f7b27..6766fcb 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/annotation/AIOp.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/annotation/AIOp.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.annotation; +package com.suifeng.sfchain.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/AuthorizationInterceptor.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/AuthorizationInterceptor.java new file mode 100644 index 0000000..b9867e6 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/AuthorizationInterceptor.java @@ -0,0 +1,74 @@ +package com.suifeng.sfchain.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * SF-Chain接口Authorization拦截器 + * 验证Authorization头是否为指定值 + * + * @author suifeng + */ +@Slf4j +@Component +public class AuthorizationInterceptor implements HandlerInterceptor { + + @Value("${sf-chain.auth-token:suifeng666}") + private String validToken; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String requestURI = request.getRequestURI(); + String method = request.getMethod(); + + // 跳过OPTIONS预检请求 + if ("OPTIONS".equalsIgnoreCase(method)) { + log.debug("跳过OPTIONS预检请求: {}", requestURI); + return true; + } + + log.debug("拦截请求: {} [{}]", requestURI, method); + + // 获取Authorization头,同时检查大小写版本 + String authorization = request.getHeader("Authorization"); + if (authorization == null || authorization.trim().isEmpty()) { + authorization = request.getHeader("authorization"); + } + + if (authorization == null || authorization.trim().isEmpty()) { + log.warn("请求缺少Authorization头: {} [{}]", requestURI, method); + sendUnauthorizedResponse(response, "缺少Authorization请求头"); + return false; + } + + // 验证token值 + String trimmedAuth = authorization.trim(); + if (!validToken.equals(trimmedAuth)) { + log.warn("Authorization验证失败: {} [{}] - 期望: [{}], 实际: [{}]", + requestURI, method, validToken, trimmedAuth); + sendUnauthorizedResponse(response, "Authorization验证失败"); + return false; + } + + log.debug("Authorization验证通过: {} [{}]", requestURI, method); + return true; + } + + private void sendUnauthorizedResponse(HttpServletResponse response, String message) throws IOException { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(String.format( + "{\"error\":\"%s\",\"code\":%d,\"message\":\"%s\"}", + "Unauthorized", + HttpStatus.UNAUTHORIZED.value(), + message + )); + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIAutoConfiguration.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIAutoConfiguration.java similarity index 90% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIAutoConfiguration.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIAutoConfiguration.java index 6ee7303..d22596e 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIAutoConfiguration.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIAutoConfiguration.java @@ -1,8 +1,8 @@ -package io.github.timemachinelab.sfchain.config; +package com.suifeng.sfchain.config; -import io.github.timemachinelab.sfchain.core.AIModel; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelConfig; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelFactory; +import com.suifeng.sfchain.core.AIModel; +import com.suifeng.sfchain.core.openai.OpenAIModelConfig; +import com.suifeng.sfchain.core.openai.OpenAIModelFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIModelsConfig.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIModelsConfig.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIModelsConfig.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIModelsConfig.java index 24784cb..30f5ca1 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/config/OpenAIModelsConfig.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/OpenAIModelsConfig.java @@ -1,6 +1,6 @@ -package io.github.timemachinelab.sfchain.config; +package com.suifeng.sfchain.config; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelConfig; +import com.suifeng.sfchain.core.openai.OpenAIModelConfig; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainAutoConfiguration.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainAutoConfiguration.java new file mode 100644 index 0000000..9d2d1af --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainAutoConfiguration.java @@ -0,0 +1,100 @@ +package com.suifeng.sfchain.config; + +import com.suifeng.sfchain.core.*; +import com.suifeng.sfchain.core.openai.OpenAIModelFactory; +import com.suifeng.sfchain.persistence.DatabaseInitializationService; +import com.suifeng.sfchain.persistence.DynamicOperationConfigService; +import com.suifeng.sfchain.persistence.PersistenceManager; +import com.suifeng.sfchain.persistence.PersistenceServiceFactory; +import com.suifeng.sfchain.persistence.config.PersistenceConfig; +import com.suifeng.sfchain.persistence.context.ChatContextService; +import com.suifeng.sfchain.persistence.context.MapBasedChatContextService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * SF-Chain 自动配置类 + * 提供框架的自动装配功能 + * + * @author suifeng + */ +@Slf4j +@AutoConfiguration +@ComponentScan(basePackages = "com.suifeng.sfchain") +@EnableJpaRepositories(basePackages = "com.suifeng.sfchain.persistence.repository") +@EntityScan(basePackages = "com.suifeng.sfchain.persistence.entity") +@EnableConfigurationProperties(PersistenceConfig.class) +@ConditionalOnProperty(prefix = "sf-chain", name = "enabled", havingValue = "true", matchIfMissing = true) +public class SfChainAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public AIOperationRegistry aiOperationRegistry() { + log.info("初始化SF-Chain AI操作注册表"); + return new AIOperationRegistry(); + } + + @Bean + @ConditionalOnMissingBean + public ModelRegistry modelRegistry(OpenAIModelFactory openAIModelFactory) { + log.info("初始化SF-Chain 模型注册表"); + return new ModelRegistry(openAIModelFactory); + } + + @Bean + @ConditionalOnMissingBean + public AIService aiService() { + log.info("初始化SF-Chain AI服务"); + return new AIService(); + } + + @Bean + @ConditionalOnMissingBean + public ChatContextService chatContextService() { + log.info("初始化SF-Chain 聊天上下文服务"); + return new MapBasedChatContextService(); + } + + @Bean + @ConditionalOnMissingBean + public PersistenceManager persistenceManager( + PersistenceServiceFactory persistenceServiceFactory, + ModelRegistry modelRegistry, + AIOperationRegistry operationRegistry, + OpenAIModelFactory modelFactory, + DynamicOperationConfigService dynamicOperationConfigService) { + log.info("初始化SF-Chain 持久化管理器"); + return new PersistenceManager( + persistenceServiceFactory, + modelRegistry, + operationRegistry, + modelFactory, + dynamicOperationConfigService + ); + } + + /** + * 数据库初始化服务 + * 只有在配置了数据库类型时才会创建 + */ + @Bean + @ConditionalOnProperty(prefix = "sf-chain.persistence", name = "database-type") + @ConditionalOnMissingBean + public DatabaseInitializationService databaseInitializationService( + PersistenceConfig persistenceConfig, + DataSource dataSource, + JdbcTemplate jdbcTemplate) { + log.info("初始化SF-Chain 数据库初始化服务"); + return new DatabaseInitializationService(persistenceConfig, dataSource, jdbcTemplate); + } +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainWebConfig.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainWebConfig.java new file mode 100644 index 0000000..4cbdd57 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/SfChainWebConfig.java @@ -0,0 +1,51 @@ +package com.suifeng.sfchain.config; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * SF-Chain Web配置 + * 注册Authorization拦截器 + * + * @author suifeng + */ +@Slf4j +@Configuration +@RequiredArgsConstructor +@ConditionalOnProperty(prefix = "sf-chain", name = "authEnabled", havingValue = "true") +public class SfChainWebConfig implements WebMvcConfigurer { + + private final AuthorizationInterceptor authorizationInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + log.info("注册SF-Chain Authorization拦截器"); + + registry.addInterceptor(authorizationInterceptor) + .addPathPatterns("/sf-chain/**") + .excludePathPatterns( + "/sf-chain/config/**", // 排除配置接口 + "/**/*.js", // 排除JS文件 + "/**/*.css", // 排除CSS文件 + "/**/*.html", // 排除HTML文件 + "/**/*.ico", // 排除图标文件 + "/**/*.svg", // 排除SVG文件 + "/**/*.png", // 排除PNG文件 + "/**/*.jpg", // 排除JPG文件 + "/**/*.jpeg", // 排除JPEG文件 + "/**/*.gif", // 排除GIF文件 + "/**/*.woff", // 排除字体文件 + "/**/*.woff2", // 排除字体文件 + "/**/*.ttf", // 排除字体文件 + "/assets/**", // 排除静态资源 + "/static/**", // 排除静态资源 + "/", // 排除根路径 + "/index.html" // 排除首页 + ) + .order(1); + } +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/WebConfig.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/WebConfig.java new file mode 100644 index 0000000..60f7f2c --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/config/WebConfig.java @@ -0,0 +1,65 @@ +package com.suifeng.sfchain.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.PathResourceResolver; + +import java.io.IOException; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 配置静态资源处理 + registry.addResourceHandler("/assets/**") + .addResourceLocations("classpath:/static/assets/") + .setCachePeriod(3600); + + registry.addResourceHandler("/favicon.ico") + .addResourceLocations("classpath:/static/favicon.ico") + .setCachePeriod(3600); + + registry.addResourceHandler("/icons/**") + .addResourceLocations("classpath:/static/icons/") + .setCachePeriod(3600); + + // 配置SPA路由支持 + registry.addResourceHandler("/**") + .addResourceLocations("classpath:/static/") + .resourceChain(true) + .addResolver(new PathResourceResolver() { + @Override + protected Resource getResource(String resourcePath, Resource location) throws IOException { + Resource requestedResource = location.createRelative(resourcePath); + + // 如果请求的资源存在,直接返回 + if (requestedResource.exists() && requestedResource.isReadable()) { + return requestedResource; + } + + // 排除API请求,对于SPA路由返回index.html + if (!resourcePath.startsWith("api/") && + !resourcePath.startsWith("sf-chain/") && + !resourcePath.contains(".")) { // 不包含文件扩展名的请求视为路由 + Resource indexHtml = new ClassPathResource("/static/index.html"); + if (indexHtml.exists()) { + return indexHtml; + } + } + + return null; + } + }); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + // 显式配置根路径映射到index.html + registry.addViewController("/").setViewName("forward:/index.html"); + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/constants/AIOperationConstant.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/constants/AIOperationConstant.java similarity index 80% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/constants/AIOperationConstant.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/constants/AIOperationConstant.java index cd80d69..c07c95f 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/constants/AIOperationConstant.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/constants/AIOperationConstant.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.constants; +package com.suifeng.sfchain.constants; /** * 描述: AI操作常量定义 @@ -19,6 +19,11 @@ public class AIOperationConstant { */ public static final String MODEL_VALIDATION_OP = "MODEL_VALIDATION_OP"; + /** + * 聊天对话操作 + */ + public static final String CHAT_OP = "CHAT"; + /** * 私有构造函数,防止实例化 */ diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AICallLogController.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AICallLogController.java similarity index 87% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AICallLogController.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AICallLogController.java index 61723d4..237cbbf 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AICallLogController.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AICallLogController.java @@ -1,8 +1,8 @@ -package io.github.timemachinelab.sfchain.controller; +package com.suifeng.sfchain.controller; -import io.github.timemachinelab.sfchain.core.logging.AICallLog; -import io.github.timemachinelab.sfchain.core.logging.AICallLogManager; -import io.github.timemachinelab.sfchain.core.logging.AICallLogSummary; +import com.suifeng.sfchain.core.logging.AICallLog; +import com.suifeng.sfchain.core.logging.AICallLogManager; +import com.suifeng.sfchain.core.logging.AICallLogSummary; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -14,7 +14,7 @@ * AI调用日志查询控制器 */ @RestController -@RequestMapping("/sf/api/ai-logs") +@RequestMapping("/sf-chain/ai-logs") public class AICallLogController { @Resource diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIModelController.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIModelController.java similarity index 83% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIModelController.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIModelController.java index ed34b96..2b1c08b 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIModelController.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIModelController.java @@ -1,11 +1,11 @@ -package io.github.timemachinelab.sfchain.controller; +package com.suifeng.sfchain.controller; -import io.github.timemachinelab.sfchain.core.AIOperationRegistry; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelConfig; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelFactory; -import io.github.timemachinelab.sfchain.operations.ModelValidationOperation; -import io.github.timemachinelab.sfchain.persistence.ModelConfigData; -import io.github.timemachinelab.sfchain.persistence.PersistenceManager; +import com.suifeng.sfchain.core.AIOperationRegistry; +import com.suifeng.sfchain.core.openai.OpenAIModelConfig; +import com.suifeng.sfchain.core.openai.OpenAIModelFactory; +import com.suifeng.sfchain.operations.ModelValidationOperation; +import com.suifeng.sfchain.persistence.ModelConfigData; +import com.suifeng.sfchain.persistence.PersistenceManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -18,7 +18,7 @@ import java.util.Map; import java.util.stream.Collectors; -import static io.github.timemachinelab.sfchain.constants.AIOperationConstant.MODEL_VALIDATION_OP; +import static com.suifeng.sfchain.constants.AIOperationConstant.MODEL_VALIDATION_OP; /** * 描述: AI模型配置管理控制器 @@ -29,7 +29,7 @@ */ @Slf4j @RestController -@RequestMapping("/sf/api/models") +@RequestMapping("/sf-chain/models") @RequiredArgsConstructor public class AIModelController { @@ -92,8 +92,12 @@ public ResponseEntity> saveModel( Map result = new HashMap<>(); String modelName = config.getModelName(); try { - // 验证模型配置 - boolean validationResult = validateModelConfig(modelName, config); + // 检查模型是否已存在 + Map existingModels = persistenceManager.getAllModelConfigs(); + boolean modelExists = existingModels.containsKey(modelName); + + // 验证模型配置(临时验证,不影响现有模型) + boolean validationResult = validateModelConfig(modelName, config, true); if (!validationResult) { result.put("success", false); @@ -101,10 +105,6 @@ public ResponseEntity> saveModel( return ResponseEntity.badRequest().body(result); } - // 检查模型是否已存在 - Map existingModels = persistenceManager.getAllModelConfigs(); - boolean modelExists = existingModels.containsKey(modelName); - // 根据模型是否存在选择添加或更新 if (modelExists) { persistenceManager.updateModelConfig(modelName, config); @@ -131,31 +131,12 @@ public ResponseEntity> saveModel( } } - /** - * 删除模型配置 - */ - @DeleteMapping("/{modelName}") - public ResponseEntity> deleteModel(@PathVariable String modelName) { - Map result = new HashMap<>(); - try { - persistenceManager.deleteModelConfig(modelName); - result.put("success", true); - result.put("message", "模型配置删除成功"); - result.put("modelName", modelName); - return ResponseEntity.ok(result); - } catch (Exception e) { - log.error("删除模型配置失败: {} - {}", modelName, e.getMessage()); - result.put("success", false); - result.put("message", "删除失败: " + e.getMessage()); - return ResponseEntity.badRequest().body(result); - } - } - /** * 测试模型连接 */ - @PostMapping("/{modelName}/test") - public ResponseEntity> testModel(@PathVariable String modelName) { + @PostMapping("/test") + public ResponseEntity> testModel(@RequestBody Map request) { + String modelName = request.get("modelName"); Map result = new HashMap<>(); try { Map models = persistenceManager.getAllModelConfigs(); @@ -167,7 +148,8 @@ public ResponseEntity> testModel(@PathVariable String modelN return ResponseEntity.notFound().build(); } - boolean testResult = validateModelConfig(modelName, config); + // 测试已存在的模型,不需要临时注册 + boolean testResult = validateModelConfig(modelName, config, false); result.put("success", testResult); result.put("message", testResult ? "模型连接测试成功" : "模型连接测试失败"); result.put("modelName", modelName); @@ -185,11 +167,14 @@ public ResponseEntity> testModel(@PathVariable String modelN /** * 验证模型配置是否可用 + * @param modelName 模型名称 + * @param config 模型配置 + * @param isTemporaryValidation 是否为临时验证(true: 验证后移除临时模型,false: 验证已存在的模型) */ - private boolean validateModelConfig(String modelName, ModelConfigData config) { + private boolean validateModelConfig(String modelName, ModelConfigData config, boolean isTemporaryValidation) { boolean tempRegistered = false; try { - log.info("开始验证模型配置: {}", modelName); + log.info("开始验证模型配置: {} (临时验证: {})", modelName, isTemporaryValidation); ModelValidationOperation validationOp = (ModelValidationOperation) operationRegistry.getOperation(MODEL_VALIDATION_OP); if (validationOp == null) { @@ -197,9 +182,12 @@ private boolean validateModelConfig(String modelName, ModelConfigData config) { return true; } - OpenAIModelConfig tempConfig = convertToOpenAIConfig(config); - modelFactory.registerModel(tempConfig); - tempRegistered = true; + // 如果是临时验证,需要临时注册模型 + if (isTemporaryValidation) { + OpenAIModelConfig tempConfig = convertToOpenAIConfig(config); + modelFactory.registerModel(tempConfig); + tempRegistered = true; + } ModelValidationOperation.ValidationRequest request = new ModelValidationOperation.ValidationRequest("请回答:2+3等于几?"); @@ -212,15 +200,38 @@ private boolean validateModelConfig(String modelName, ModelConfigData config) { log.error("模型验证失败: {} - {}", modelName, e.getMessage()); return false; } finally { - if (tempRegistered) { + // 只有在临时验证时才清理临时模型 + if (tempRegistered && isTemporaryValidation) { try { modelFactory.removeModel(modelName); + log.debug("已清理临时模型配置: {}", modelName); } catch (Exception e) { log.warn("清理临时模型配置失败: {}", e.getMessage()); } } } } + + + /** + * 删除模型配置 + */ + @DeleteMapping("/{modelName}") + public ResponseEntity> deleteModel(@PathVariable String modelName) { + Map result = new HashMap<>(); + try { + persistenceManager.deleteModelConfig(modelName); + result.put("success", true); + result.put("message", "模型配置删除成功"); + result.put("modelName", modelName); + return ResponseEntity.ok(result); + } catch (Exception e) { + log.error("删除模型配置失败: {} - {}", modelName, e.getMessage()); + result.put("success", false); + result.put("message", "删除失败: " + e.getMessage()); + return ResponseEntity.badRequest().body(result); + } + } /** * 转换配置格式 diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIOperationController.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIOperationController.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIOperationController.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIOperationController.java index 5aa7aa1..cc68df3 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AIOperationController.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AIOperationController.java @@ -1,8 +1,8 @@ -package io.github.timemachinelab.sfchain.controller; +package com.suifeng.sfchain.controller; -import io.github.timemachinelab.sfchain.persistence.ModelConfigData; -import io.github.timemachinelab.sfchain.persistence.OperationConfigData; -import io.github.timemachinelab.sfchain.persistence.PersistenceManager; +import com.suifeng.sfchain.persistence.ModelConfigData; +import com.suifeng.sfchain.persistence.OperationConfigData; +import com.suifeng.sfchain.persistence.PersistenceManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -23,7 +23,7 @@ */ @Slf4j @RestController -@RequestMapping("/sf/api/operations") +@RequestMapping("/sf-chain/operations") @RequiredArgsConstructor public class AIOperationController { diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AISystemController.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AISystemController.java similarity index 90% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AISystemController.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AISystemController.java index e443989..5c510d4 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/controller/AISystemController.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/AISystemController.java @@ -1,13 +1,16 @@ -package io.github.timemachinelab.sfchain.controller; +package com.suifeng.sfchain.controller; -import io.github.timemachinelab.sfchain.persistence.ModelConfigData; -import io.github.timemachinelab.sfchain.persistence.OperationConfigData; -import io.github.timemachinelab.sfchain.persistence.PersistenceManager; +import com.suifeng.sfchain.persistence.ModelConfigData; +import com.suifeng.sfchain.persistence.OperationConfigData; +import com.suifeng.sfchain.persistence.PersistenceManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @@ -21,7 +24,7 @@ */ @Slf4j @RestController -@RequestMapping("/sf/api/system") +@RequestMapping("/sf-chain/system") @RequiredArgsConstructor public class AISystemController { diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/SfChainConfigController.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/SfChainConfigController.java new file mode 100644 index 0000000..e4fb00f --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/controller/SfChainConfigController.java @@ -0,0 +1,40 @@ +package com.suifeng.sfchain.controller; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/sf-chain/config") +public class SfChainConfigController { + + @Value("${server.port:8080}") + private String serverPort; + + @Value("${server.servlet.context-path:}") + private String contextPath; + + @GetMapping("/api-info") + public Map getApiInfo() { + Map config = new HashMap<>(); + + // 构建基础URL + String baseUrl = contextPath.isEmpty() ? "" : contextPath; + + config.put("baseUrl", baseUrl); + config.put("port", serverPort); + config.put("contextPath", contextPath); + config.put("endpoints", Map.of( + "AI_MODELS", baseUrl + "/sf-chain/models", + "AI_OPERATIONS", baseUrl + "/sf-chain/operations", + "AI_CALL_LOGS", baseUrl + "/sf-chain/call-logs", + "AI_SYSTEM", baseUrl + "/sf-chain/system" + )); + + return config; + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIModel.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIModel.java similarity index 93% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIModel.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIModel.java index 32cd7ba..e67b2b6 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIModel.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIModel.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core; +package com.suifeng.sfchain.core; /** * 描述: AI模型接口 diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIOperationRegistry.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIOperationRegistry.java similarity index 98% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIOperationRegistry.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIOperationRegistry.java index 61af4c7..33cbe6f 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIOperationRegistry.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIOperationRegistry.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core; +package com.suifeng.sfchain.core; import lombok.Getter; import lombok.Setter; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIPromptBuilder.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIPromptBuilder.java similarity index 99% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIPromptBuilder.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIPromptBuilder.java index c624b86..b00848b 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIPromptBuilder.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIPromptBuilder.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core; +package com.suifeng.sfchain.core; import java.time.LocalDateTime; import java.time.ZoneId; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIService.java similarity index 82% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIService.java index f914e0f..16addf8 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/AIService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/AIService.java @@ -1,9 +1,10 @@ -package io.github.timemachinelab.sfchain.core; +package com.suifeng.sfchain.core; -import io.github.timemachinelab.sfchain.persistence.context.ChatContextService; +import com.suifeng.sfchain.persistence.context.ChatContextService; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; import javax.annotation.Resource; import java.util.List; @@ -203,7 +204,71 @@ public CompletableFuture executeAsync(String operationTy return CompletableFuture.supplyAsync(() -> execute(operationType, input, modelName, sessionId)); } - // ... existing code ... + /** + * 流式执行AI操作 + */ + @SuppressWarnings("unchecked") + public Flux executeStream(String operationType, INPUT input) { + return executeStream(operationType, input, null, null); + } + + /** + * 流式执行AI操作(指定模型) + */ + @SuppressWarnings("unchecked") + public Flux executeStream(String operationType, INPUT input, String modelName) { + return executeStream(operationType, input, modelName, null); + } + + /** + * 流式执行AI操作(带上下文支持) + */ + @SuppressWarnings("unchecked") + public Flux executeStream(String operationType, INPUT input, String modelName, String sessionId) { + try { + // 获取操作实例 + BaseAIOperation operation = (BaseAIOperation) operationRegistry.getOperation(operationType); + + // 检查操作是否启用 + if (!operation.isEnabled()) { + return Flux.error(new IllegalStateException("操作已禁用: " + operationType)); + } + + // 如果有会话ID,记录用户输入到上下文 + if (sessionId != null && input != null) { + chatContextService.addUserMessage(sessionId, input.toString()); + } + + // 用于收集流式响应的StringBuilder + StringBuilder responseBuilder = new StringBuilder(); + + // 执行流式操作 - 修复参数传递 + return operation.executeStream(input, modelName, sessionId) + .doOnNext(chunk -> { + // 收集每个响应片段 + if (sessionId != null && chunk != null) { + responseBuilder.append(chunk); + } + }) + .doOnSubscribe(subscription -> { + log.debug("开始流式执行AI操作: {}", operationType); + }) + .doOnComplete(() -> { + // 流完成时,将完整的AI响应添加到上下文 + if (sessionId != null && responseBuilder.length() > 0) { + chatContextService.addAiResponse(sessionId, responseBuilder.toString()); + } + log.debug("流式AI操作执行完成: {}", operationType); + }) + .doOnError(error -> { + log.error("流式AI操作执行失败: {} - {}", operationType, error.getMessage(), error); + }); + + } catch (Exception e) { + log.error("流式AI操作执行失败: {} - {}", operationType, e.getMessage(), e); + return Flux.error(new RuntimeException("流式AI操作执行失败: " + e.getMessage(), e)); + } + } /** * 批量执行AI操作 @@ -353,8 +418,6 @@ private void recordExecution(String operationType, boolean success, long duratio .record(success, duration); } - // ... existing inner classes remain the same ... - /** * 操作信息类 */ diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/BaseAIOperation.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/BaseAIOperation.java similarity index 79% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/BaseAIOperation.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/BaseAIOperation.java index 1b6bc95..adc5800 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/BaseAIOperation.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/BaseAIOperation.java @@ -1,17 +1,18 @@ -package io.github.timemachinelab.sfchain.core; - -import com.alibaba.fastjson.JSONObject; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.logging.AICallLog; -import io.github.timemachinelab.sfchain.core.logging.AICallLogManager; -import io.github.timemachinelab.sfchain.core.openai.OpenAICompatibleModel; -import io.github.timemachinelab.sfchain.persistence.context.ChatContextService; -import io.github.timemachinelab.sfchain.persistence.context.ChatMessage; +package com.suifeng.sfchain.core; + +import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.logging.AICallLog; +import com.suifeng.sfchain.core.logging.AICallLogManager; +import com.suifeng.sfchain.core.openai.OpenAICompatibleModel; +import com.suifeng.sfchain.persistence.context.ChatContextService; +import com.suifeng.sfchain.persistence.context.ChatMessage; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import reactor.core.publisher.Flux; import javax.annotation.PostConstruct; import java.lang.reflect.ParameterizedType; @@ -20,7 +21,7 @@ import java.util.List; import java.util.UUID; -import static io.github.timemachinelab.sfchain.constants.AIOperationConstant.JSON_REPAIR_OP; +import static com.suifeng.sfchain.constants.AIOperationConstant.JSON_REPAIR_OP; /** * 描述: AI操作抽象基类 - 新框架版本 @@ -47,7 +48,7 @@ public abstract class BaseAIOperation { /** * 操作的注解信息 * -- GETTER -- - * 获取注解信息 + * 获取注解信息 * * @return 注解信息 */ @@ -57,10 +58,9 @@ public abstract class BaseAIOperation { /** * 输入类型 * -- GETTER -- - * 获取输入类型 + * 获取输入类型 * * @return 输入类型 - */ @Getter private Class inputType; @@ -68,10 +68,9 @@ public abstract class BaseAIOperation { /** * 输出类型 * -- GETTER -- - * 获取输出类型 + * 获取输出类型 * * @return 输出类型 - */ @Getter private Class outputType; @@ -123,6 +122,68 @@ public void init() { outputType != null ? outputType.getSimpleName() : "Unknown"); } + /** + * 流式执行AI操作 + */ + @SuppressWarnings("unchecked") + public Flux executeStream(INPUT input) { + return executeStream(input, null, null); + } + + /** + * 流式执行AI操作(指定模型) + */ + @SuppressWarnings("unchecked") + public Flux executeStream(INPUT input, String modelName) { + return executeStream(input, modelName, null); + } + + /** + * 流式执行AI操作(带上下文支持) + */ + @SuppressWarnings("unchecked") + public Flux executeStream(INPUT input, String modelName, String sessionId) { + try { + // 检查操作是否启用 + if (!isEnabled()) { + return Flux.error(new IllegalStateException("操作已禁用: " + annotation.value())); + } + + // 获取模型 + AIModel model = getModel(modelName); + + // 构建带上下文的提示词 + String prompt = buildPromptWithContext(input, sessionId); + + // 获取操作配置 + AIOperationRegistry.OperationConfig config = operationRegistry.getOperationConfig(annotation.value()); + + // 合并配置 + Integer finalMaxTokens = config.getMaxTokens() > 0 ? Integer.valueOf(config.getMaxTokens()) : + (annotation.defaultMaxTokens() > 0 ? annotation.defaultMaxTokens() : null); + Double finalTemperature = config.getTemperature() >= 0 ? Double.valueOf(config.getTemperature()) : + (annotation.defaultTemperature() >= 0 ? annotation.defaultTemperature() : null); + Boolean finalJsonOutput = config.isRequireJsonOutput() || annotation.requireJsonOutput(); + boolean finalThinking = config.isSupportThinking() || annotation.supportThinking(); + + // 调用模型的流式生成方法 + if (model instanceof OpenAICompatibleModel openAIModel) { + if (finalThinking) { + return openAIModel.generateStreamWithThinking(prompt, finalMaxTokens, finalTemperature); + } else { + return openAIModel.generateStream(prompt, finalMaxTokens, finalTemperature, finalJsonOutput); + } + } else { + // 对于不支持流式的模型,返回错误 + return Flux.error(new UnsupportedOperationException("模型不支持流式输出: " + model.getName())); + } + + } catch (Exception e) { + log.error("流式AI操作执行失败: {} - {}", annotation.value(), e.getMessage(), e); + return Flux.error(new RuntimeException("流式AI操作执行失败: " + e.getMessage(), e)); + } + } + /** * 执行AI操作 * @@ -136,7 +197,7 @@ public OUTPUT execute(INPUT input) { /** * 执行AI操作(指定模型) * - * @param input 输入参数 + * @param input 输入参数 * @param modelName 指定的模型名称,为null时使用默认模型 * @return 输出结果 */ @@ -247,7 +308,7 @@ public OUTPUT execute(INPUT input, String modelName, String sessionId) { /** * 构建带上下文的提示词 * - * @param input 输入参数 + * @param input 输入参数 * @param sessionId 会话ID * @return 完整的提示词 */ @@ -319,20 +380,39 @@ private String getRoleString(ChatMessage.MessageType type) { */ protected abstract String buildPrompt(INPUT input); - // ... existing code remains the same ... - /** * 解析AI响应(最终方法,子类不应重写) + * 重写版本:支持非JSON格式输出 * * @param response AI响应 - * @param input 输入参数 + * @param input 输入参数 * @return 解析后的结果 */ protected final OUTPUT parseResponse(String response, INPUT input) { + // 如果输出类型是String,直接返回响应内容 if (outputType == String.class) { + // 先尝试子类自定义解析 + OUTPUT customResult = parseResult(response, input); + if (customResult != null) { + return customResult; + } + // 默认返回原始响应 return (OUTPUT) response; } + // 如果不要求JSON输出,也尝试直接解析 + if (!annotation.requireJsonOutput()) { + OUTPUT customResult = parseResult(response, input); + if (customResult != null) { + return customResult; + } + // 如果子类没有自定义解析且不要求JSON,返回原始响应(如果类型兼容) + if (outputType.isAssignableFrom(String.class)) { + return (OUTPUT) response; + } + } + + // 以下是原有的JSON解析逻辑 try { // 1. 预处理响应(子类可自定义) String processedResponse = preprocessResponse(response, input); @@ -377,7 +457,7 @@ protected final OUTPUT parseResponse(String response, INPUT input) { * 在提取JSON之前对原始响应进行处理 * * @param response 原始AI响应 - * @param input 输入参数 + * @param input 输入参数 * @return 处理后的响应 */ protected String preprocessResponse(String response, INPUT input) { @@ -389,7 +469,7 @@ protected String preprocessResponse(String response, INPUT input) { * 在JSON解析之前对提取的JSON字符串进行处理 * * @param jsonContent 提取的JSON字符串 - * @param input 输入参数 + * @param input 输入参数 * @return 处理后的JSON字符串 */ protected String preprocessJson(String jsonContent, INPUT input) { @@ -399,8 +479,8 @@ protected String preprocessJson(String jsonContent, INPUT input) { /** * 将JSON字符串解析为结果对象(高级用法,一般用户无需重写) * - * @param jsonContent JSON内容 - * @param input 输入参数 + * @param jsonContent JSON内容 + * @param input 输入参数 * @param originalResponse 原始响应 * @return 解析后的结果对象 * @throws JsonProcessingException JSON解析异常 @@ -421,7 +501,7 @@ protected OUTPUT parseJsonToResult(String jsonContent, INPUT input, String origi * 用户可以在此方法中处理AI返回的原始JSON,并转换为最终的结果对象 * * @param jsonContent AI返回的JSON字符串 - * @param input 输入参数 + * @param input 输入参数 * @return 最终结果对象,如果返回null则使用默认的JSON解析 */ protected OUTPUT parseResult(String jsonContent, INPUT input) { @@ -432,8 +512,8 @@ protected OUTPUT parseResult(String jsonContent, INPUT input) { * 工具方法:将JSON字符串解析为指定类型的对象 * * @param jsonContent JSON字符串 - * @param clazz 目标类型 - * @param 泛型类型 + * @param clazz 目标类型 + * @param 泛型类型 * @return 解析后的对象 * @throws JsonProcessingException JSON解析异常 */ @@ -537,4 +617,5 @@ public String getDescription() { public String[] getSupportedModels() { return annotation.supportedModels(); } -} \ No newline at end of file + +} diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/ModelRegistry.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/ModelRegistry.java similarity index 94% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/ModelRegistry.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/ModelRegistry.java index cc7d3b7..dcce7f2 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/ModelRegistry.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/ModelRegistry.java @@ -1,6 +1,6 @@ -package io.github.timemachinelab.sfchain.core; +package com.suifeng.sfchain.core; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelFactory; +import com.suifeng.sfchain.core.openai.OpenAIModelFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLog.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLog.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLog.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLog.java index f956bad..779a3b7 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLog.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLog.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.logging; +package com.suifeng.sfchain.core.logging; import lombok.Builder; import lombok.Data; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogAspect.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogAspect.java similarity index 93% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogAspect.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogAspect.java index b5928fe..6c2c450 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogAspect.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogAspect.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.logging; +package com.suifeng.sfchain.core.logging; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -24,7 +24,7 @@ public class AICallLogAspect { /** * 拦截BaseAIOperation的execute方法 */ - @Around("execution(* io.github.timemachinelab.sfchain.core.BaseAIOperation.execute(..))") + @Around("execution(* com.suifeng.sfchain.core.BaseAIOperation.execute(..))") public Object logAIOperation(ProceedingJoinPoint joinPoint) throws Throwable { String callId = UUID.randomUUID().toString(); LocalDateTime startTime = LocalDateTime.now(); diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogManager.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogManager.java similarity index 99% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogManager.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogManager.java index 5391b49..8e956d3 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogManager.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogManager.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.logging; +package com.suifeng.sfchain.core.logging; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogSummary.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogSummary.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogSummary.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogSummary.java index 10e9890..36ccd91 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/logging/AICallLogSummary.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/logging/AICallLogSummary.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.logging; +package com.suifeng.sfchain.core.logging; import lombok.Builder; import lombok.Data; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAICompatibleModel.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAICompatibleModel.java similarity index 60% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAICompatibleModel.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAICompatibleModel.java index 3337b02..07ec355 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAICompatibleModel.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAICompatibleModel.java @@ -1,9 +1,10 @@ -package io.github.timemachinelab.sfchain.core.openai; +package com.suifeng.sfchain.core.openai; import com.alibaba.fastjson2.JSON; -import io.github.timemachinelab.sfchain.core.AIModel; +import com.suifeng.sfchain.core.AIModel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import reactor.core.publisher.Flux; import java.util.List; import java.util.Map; @@ -152,4 +153,85 @@ private OpenAIRequest buildRequestWithThinking(String prompt, Integer maxTokens, public boolean isAvailable() { return Boolean.TRUE.equals(config.getEnabled()) && config.isValid(); } + + /** + * 流式生成响应 + */ + public Flux generateStream(String prompt) { + return generateStream(prompt, null, null, null); + } + + /** + * 流式生成响应 - 支持自定义参数 + */ + public Flux generateStream(String prompt, Integer maxTokens, Double temperature, Boolean jsonOutput) { + try { + OpenAIRequest request = buildStreamRequest(prompt, maxTokens, temperature, jsonOutput); + return httpClient.chatCompletionStream(request); + } catch (Exception e) { + log.error("模型{}流式生成失败", config.getModelName(), e); + return Flux.error(new RuntimeException("模型流式生成失败: " + e.getMessage(), e)); + } + } + + /** + * 流式生成响应 - 支持思考模式 + */ + public Flux generateStreamWithThinking(String prompt, Integer maxTokens, Double temperature) { + if (!Boolean.TRUE.equals(config.getSupportThinking())) { + log.warn("模型{}不支持思考模式,使用普通流式模式", config.getModelName()); + return generateStream(prompt, maxTokens, temperature, null); + } + + try { + OpenAIRequest request = buildStreamRequestWithThinking(prompt, maxTokens, temperature); + return httpClient.chatCompletionStream(request); + } catch (Exception e) { + log.error("模型{}思考模式流式生成失败", config.getModelName(), e); + return Flux.error(new RuntimeException("思考模式流式生成失败: " + e.getMessage(), e)); + } + } + + /** + * 构建流式请求对象 + */ + private OpenAIRequest buildStreamRequest(String prompt, Integer maxTokens, Double temperature, Boolean jsonOutput) { + var builder = OpenAIRequest.builder() + .model(config.getModelName()) + .messages(List.of( + OpenAIRequest.Message.builder() + .role("user") + .content(prompt) + .build() + )) + .max_tokens(maxTokens != null ? maxTokens : config.getDefaultMaxTokens()) + .temperature(temperature != null ? temperature : config.getDefaultTemperature()) + .stream(true); // 设置为true以启用流式输出 + + // 设置JSON输出格式 + if (Boolean.TRUE.equals(jsonOutput) && Boolean.TRUE.equals(config.getSupportJsonOutput())) { + builder.response_format(Map.of("type", "json_object")); + } + + return builder.build(); + } + + /** + * 构建带思考模式的流式请求对象 + */ + private OpenAIRequest buildStreamRequestWithThinking(String prompt, Integer maxTokens, Double temperature) { + return OpenAIRequest.builder() + .model(config.getModelName()) + .messages(List.of( + OpenAIRequest.Message.builder() + .role("user") + .content(prompt) + .build() + )) + .max_tokens(maxTokens != null ? maxTokens : config.getDefaultMaxTokens()) + .temperature(temperature != null ? temperature : config.getDefaultTemperature()) + .stream(true) + .enable_thinking(true) + .build(); + } } \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIHttpClient.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIHttpClient.java new file mode 100644 index 0000000..3415373 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIHttpClient.java @@ -0,0 +1,256 @@ +package com.suifeng.sfchain.core.openai; + +import com.alibaba.fastjson2.JSON; +import lombok.extern.slf4j.Slf4j; +import reactor.core.publisher.Flux; +import reactor.core.publisher.FluxSink; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * 描述: OpenAI兼容的HTTP客户端 + * @author suifeng + * 日期: 2025/8/11 + */ +@Slf4j +public class OpenAIHttpClient { + + private final String baseUrl; + private final String apiKey; + private final Map defaultHeaders; + + public OpenAIHttpClient(String baseUrl, String apiKey) { + this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl; + this.apiKey = apiKey; + this.defaultHeaders = Map.of( + "Content-Type", "application/json", + "Authorization", "Bearer " + apiKey + ); + } + + public OpenAIHttpClient(String baseUrl, String apiKey, Map additionalHeaders) { + this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl; + this.apiKey = apiKey; + this.defaultHeaders = new HashMap<>(); + this.defaultHeaders.put("Content-Type", "application/json"); + this.defaultHeaders.put("Authorization", "Bearer " + apiKey); + if (additionalHeaders != null) { + this.defaultHeaders.putAll(additionalHeaders); + } + } + + /** + * 发送聊天完成请求 + */ + public OpenAIResponse chatCompletion(OpenAIRequest request) { + try { + // 智能构建endpoint,避免重复的/v1路径 + String endpoint; + if (baseUrl.endsWith("/v1") || baseUrl.contains("/v1/")) { + // baseUrl已包含v1路径,直接添加chat/completions + endpoint = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "chat/completions"; + } else { + // baseUrl不包含v1路径,添加完整路径 + endpoint = baseUrl + "/v1/chat/completions"; + } + String requestBody = JSON.toJSONString(request); + + log.debug("发送请求到: {}", endpoint); + log.debug("请求体: {}", requestBody); + log.info("构建的API端点: {}", endpoint); + + HttpURLConnection connection = createConnection(endpoint); + + // 发送请求体 + try (OutputStream os = connection.getOutputStream()) { + byte[] input = requestBody.getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + // 读取响应 + StringBuilder response = new StringBuilder(); + int responseCode = connection.getResponseCode(); + + if (responseCode == HttpURLConnection.HTTP_OK) { + try (BufferedReader br = new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = br.readLine()) != null) { + response.append(line); + } + } + } else { + // 读取错误响应 + try (BufferedReader br = new BufferedReader( + new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = br.readLine()) != null) { + response.append(line); + } + } + throw new RuntimeException("HTTP请求失败,状态码: " + responseCode + ", 响应: " + response.toString()); + } + + String responseBody = response.toString(); + log.debug("响应体: {}", responseBody); + + return JSON.parseObject(responseBody, OpenAIResponse.class); + + } catch (Exception e) { + log.error("OpenAI API调用失败", e); + throw new RuntimeException("OpenAI API调用失败: " + e.getMessage(), e); + } + } + + /** + * 创建HTTP连接 + */ + private HttpURLConnection createConnection(String endpoint) throws Exception { + URL url = new URL(endpoint); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setConnectTimeout(30000); // 30秒连接超时 + connection.setReadTimeout(120000); // 120秒读取超时 + + // 设置请求头 + defaultHeaders.forEach(connection::setRequestProperty); + + return connection; + } + + /** + * 提取响应内容 + */ + public String extractContent(OpenAIResponse response) { + if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) { + return ""; + } + + OpenAIResponse.Choice choice = response.getChoices().get(0); + if (choice.getMessage() != null && choice.getMessage().getContent() != null) { + return choice.getMessage().getContent(); + } + + return ""; + } + + /** + * 发送流式聊天完成请求 + */ + public Flux chatCompletionStream(OpenAIRequest request) { + return Flux.create(sink -> { + // 在新线程中异步处理流式响应 + CompletableFuture.runAsync(() -> { + try { + // 设置流式请求 + OpenAIRequest streamRequest = request.toBuilder().stream(true).build(); + + // 智能构建endpoint + String endpoint; + if (baseUrl.endsWith("/v1") || baseUrl.contains("/v1/")) { + endpoint = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "chat/completions"; + } else { + endpoint = baseUrl + "/v1/chat/completions"; + } + + String requestBody = JSON.toJSONString(streamRequest); + log.debug("发送流式请求到: {}", endpoint); + log.debug("请求体: {}", requestBody); + + HttpURLConnection connection = createConnection(endpoint); + + // 发送请求体 + try (OutputStream os = connection.getOutputStream()) { + byte[] input = requestBody.getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + // 读取流式响应 + int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + + String line; + while ((line = reader.readLine()) != null && !sink.isCancelled()) { + if (line.trim().isEmpty()) { + continue; + } + + // 处理SSE格式的数据 + if (line.startsWith("data: ")) { + String data = line.substring(6).trim(); + + // 检查是否为结束标记 + if ("[DONE]".equals(data)) { + sink.complete(); + break; + } + + try { + // 解析流式响应 + OpenAIStreamResponse streamResponse = JSON.parseObject(data, OpenAIStreamResponse.class); + String content = extractStreamContent(streamResponse); + if (content != null && !content.isEmpty()) { + // 立即发送内容,而不是缓存 + sink.next(content); + // 添加小延迟以确保流式效果 + Thread.sleep(10); + } + } catch (Exception e) { + log.warn("解析流式响应失败: {}", data, e); + } + } + } + + if (!sink.isCancelled()) { + sink.complete(); + } + } + } else { + // 读取错误响应 + StringBuilder errorResponse = new StringBuilder(); + try (BufferedReader br = new BufferedReader( + new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = br.readLine()) != null) { + errorResponse.append(line); + } + } + sink.error(new RuntimeException("HTTP请求失败,状态码: " + responseCode + ", 响应: " + errorResponse.toString())); + } + + } catch (Exception e) { + log.error("流式OpenAI API调用失败", e); + sink.error(new RuntimeException("流式OpenAI API调用失败: " + e.getMessage(), e)); + } + }); + }, FluxSink.OverflowStrategy.BUFFER); + } + + /** + * 提取流式响应内容 + */ + private String extractStreamContent(OpenAIStreamResponse response) { + if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) { + return null; + } + + OpenAIStreamResponse.StreamChoice choice = response.getChoices().get(0); + if (choice.getDelta() != null && choice.getDelta().getContent() != null) { + return choice.getDelta().getContent(); + } + + return null; + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelConfig.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelConfig.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelConfig.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelConfig.java index f7b2a42..d8c9efb 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelConfig.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelConfig.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.openai; +package com.suifeng.sfchain.core.openai; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelFactory.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelFactory.java similarity index 95% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelFactory.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelFactory.java index 1f9c3ad..7394cd9 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIModelFactory.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIModelFactory.java @@ -1,6 +1,6 @@ -package io.github.timemachinelab.sfchain.core.openai; +package com.suifeng.sfchain.core.openai; -import io.github.timemachinelab.sfchain.core.AIModel; +import com.suifeng.sfchain.core.AIModel; import lombok.extern.slf4j.Slf4j; import java.util.Map; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIRequest.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIRequest.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIRequest.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIRequest.java index 181cdcf..66d78cf 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIRequest.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIRequest.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.openai; +package com.suifeng.sfchain.core.openai; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIResponse.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIResponse.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIResponse.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIResponse.java index 83a80da..ff23ffd 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIResponse.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIResponse.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.core.openai; +package com.suifeng.sfchain.core.openai; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIStreamResponse.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIStreamResponse.java new file mode 100644 index 0000000..cd6b00b --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/core/openai/OpenAIStreamResponse.java @@ -0,0 +1,88 @@ +package com.suifeng.sfchain.core.openai; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 描述: OpenAI兼容的流式响应体 + * @author suifeng + * 日期: 2025/8/11 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OpenAIStreamResponse { + + /** + * 响应ID + */ + private String id; + + /** + * 对象类型 + */ + private String object; + + /** + * 创建时间戳 + */ + private Long created; + + /** + * 模型名称 + */ + private String model; + + /** + * 选择列表 + */ + private List choices; + + /** + * 系统指纹 + */ + private String system_fingerprint; + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class StreamChoice { + /** + * 选择索引 + */ + private Integer index; + + /** + * 增量消息内容 + */ + private Delta delta; + + /** + * 完成原因 + */ + private String finish_reason; + + /** + * logprobs (可选) + */ + private Object logprobs; + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class Delta { + /** + * 角色 (仅在第一个chunk中出现) + */ + private String role; + + /** + * 增量内容 + */ + private String content; + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/JSONRepairOperation.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/JSONRepairOperation.java similarity index 93% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/JSONRepairOperation.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/JSONRepairOperation.java index ce2dd49..ac35ec3 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/JSONRepairOperation.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/JSONRepairOperation.java @@ -1,15 +1,15 @@ -package io.github.timemachinelab.sfchain.operations; +package com.suifeng.sfchain.operations; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.BaseAIOperation; import org.springframework.stereotype.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static io.github.timemachinelab.sfchain.constants.AIOperationConstant.JSON_REPAIR_OP; +import static com.suifeng.sfchain.constants.AIOperationConstant.JSON_REPAIR_OP; /** diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/ModelValidationOperation.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/ModelValidationOperation.java similarity index 89% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/ModelValidationOperation.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/ModelValidationOperation.java index d9cc6f5..969e749 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/operations/ModelValidationOperation.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/operations/ModelValidationOperation.java @@ -1,13 +1,13 @@ -package io.github.timemachinelab.sfchain.operations; +package com.suifeng.sfchain.operations; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; import com.fasterxml.jackson.annotation.JsonProperty; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.BaseAIOperation; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import static io.github.timemachinelab.sfchain.constants.AIOperationConstant.MODEL_VALIDATION_OP; +import static com.suifeng.sfchain.constants.AIOperationConstant.MODEL_VALIDATION_OP; /** * 描述: 模型验证操作 - 用于验证模型配置是否可用 diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DatabaseInitializationService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DatabaseInitializationService.java new file mode 100644 index 0000000..9d50e38 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DatabaseInitializationService.java @@ -0,0 +1,125 @@ +package com.suifeng.sfchain.persistence; + +import com.suifeng.sfchain.persistence.config.DatabaseType; +import com.suifeng.sfchain.persistence.config.PersistenceConfig; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.init.ScriptUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * 数据库初始化服务 + * 根据配置的数据库类型自动执行对应的migration脚本 + * + * @author suifeng + * 日期: 2025/1/27 + */ +@Slf4j +@Service +@RequiredArgsConstructor +@ConditionalOnProperty(prefix = "sf-chain.persistence", name = "database-type") +public class DatabaseInitializationService { + + private final PersistenceConfig persistenceConfig; + private final DataSource dataSource; + private final JdbcTemplate jdbcTemplate; + + /** + * 应用启动后自动执行数据库初始化 + */ + @PostConstruct + @Transactional + public void initializeDatabase() { + try { + DatabaseType databaseType = persistenceConfig.getDatabaseTypeEnum(); + log.info("检测到数据库类型配置: {},开始执行数据库初始化", databaseType); + + // 检查是否需要初始化 + if (shouldInitialize(databaseType)) { + executeMigrationScript(databaseType); + log.info("数据库初始化完成: {}", databaseType); + } else { + log.info("数据库已存在相关表,跳过初始化: {}", databaseType); + } + + } catch (Exception e) { + log.error("数据库初始化失败", e); + throw new RuntimeException("数据库初始化失败", e); + } + } + + /** + * 检查是否需要执行数据库初始化 + * 通过检查核心表是否存在来判断 + */ + private boolean shouldInitialize(DatabaseType databaseType) { + try { + String checkTableSql; + switch (databaseType) { + case MYSQL: + checkTableSql = "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_schema = DATABASE() AND table_name = 'sfchain_model_configs'"; + break; + case POSTGRESQL: + checkTableSql = "SELECT COUNT(*) FROM information_schema.tables " + + "WHERE table_name = 'sfchain_model_configs' AND table_schema = 'public'"; + break; + default: + log.warn("不支持的数据库类型: {}", databaseType); + return false; + } + + Integer count = jdbcTemplate.queryForObject(checkTableSql, Integer.class); + return count == null || count == 0; + + } catch (Exception e) { + log.debug("检查表存在性时出现异常,假设需要初始化: {}", e.getMessage()); + return true; + } + } + + /** + * 执行对应数据库类型的migration脚本 + */ + private void executeMigrationScript(DatabaseType databaseType) throws SQLException { + String scriptPath = getMigrationScriptPath(databaseType); + log.info("执行数据库脚本: {}", scriptPath); + + try (Connection connection = dataSource.getConnection()) { + ClassPathResource resource = new ClassPathResource(scriptPath); + if (!resource.exists()) { + throw new RuntimeException("Migration脚本不存在: " + scriptPath); + } + + ScriptUtils.executeSqlScript(connection, resource); + log.info("成功执行数据库脚本: {}", scriptPath); + + } catch (Exception e) { + log.error("执行数据库脚本失败: {}", scriptPath, e); + throw new SQLException("执行数据库脚本失败: " + scriptPath, e); + } + } + + /** + * 根据数据库类型获取对应的migration脚本路径 + */ + private String getMigrationScriptPath(DatabaseType databaseType) { + switch (databaseType) { + case MYSQL: + return "migration/v1_mysql.sql"; + case POSTGRESQL: + return "migration/v1_postgresql.sql"; + default: + throw new IllegalArgumentException("不支持的数据库类型: " + databaseType); + } + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/DynamicOperationConfigService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DynamicOperationConfigService.java similarity index 91% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/DynamicOperationConfigService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DynamicOperationConfigService.java index 63f5e13..9f49f6d 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/DynamicOperationConfigService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/DynamicOperationConfigService.java @@ -1,8 +1,8 @@ -package io.github.timemachinelab.sfchain.persistence; +package com.suifeng.sfchain.persistence; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.AIOperationRegistry; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.AIOperationRegistry; +import com.suifeng.sfchain.core.BaseAIOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/ModelConfigData.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/ModelConfigData.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/ModelConfigData.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/ModelConfigData.java index c539f41..d7784c5 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/ModelConfigData.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/ModelConfigData.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence; +package com.suifeng.sfchain.persistence; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/MySQLPersistenceService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/MySQLPersistenceService.java new file mode 100644 index 0000000..67d6405 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/MySQLPersistenceService.java @@ -0,0 +1,314 @@ +package com.suifeng.sfchain.persistence; + +import com.suifeng.sfchain.persistence.entity.ModelConfigEntity; +import com.suifeng.sfchain.persistence.entity.OperationConfigEntity; +import com.suifeng.sfchain.persistence.repository.ModelConfigRepository; +import com.suifeng.sfchain.persistence.repository.OperationConfigRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * 描述: 基于MySQL的持久化服务实现 + * 针对MySQL数据库的特定优化 + * + * @author suifeng + * 日期: 2025/1/27 + */ +@Slf4j +@Service +@RequiredArgsConstructor +@ConditionalOnProperty(name = "sf-chain.persistence.database-type", havingValue = "mysql") +public class MySQLPersistenceService implements PersistenceService { + + private final ModelConfigRepository modelConfigRepository; + private final OperationConfigRepository operationConfigRepository; + + @Override + @Transactional + public void saveModelConfig(String modelName, ModelConfigData config) { + log.debug("[MySQL] 保存模型配置: {}", modelName); + config.setModelName(modelName); + + // MySQL特定的保存逻辑,使用ON DUPLICATE KEY UPDATE + ModelConfigEntity entity = modelConfigRepository.findByModelName(modelName) + .map(existing -> { + // 更新现有实体 + Long id = existing.getId(); + LocalDateTime createdAt = existing.getCreatedAt(); + + ModelConfigEntity updatedEntity = convertToEntity(config); + updatedEntity.setId(id); + updatedEntity.setCreatedAt(createdAt); + + return updatedEntity; + }) + .orElseGet(() -> convertToEntity(config)); + + modelConfigRepository.save(entity); + log.info("[MySQL] 模型配置保存成功: {}", modelName); + } + + @Override + public Optional getModelConfig(String modelName) { + log.debug("[MySQL] 获取模型配置: {}", modelName); + return modelConfigRepository.findByModelName(modelName) + .map(this::convertToData); + } + + @Override + public Map getAllModelConfigs() { + log.debug("[MySQL] 获取所有模型配置"); + return modelConfigRepository.findAll().stream() + .collect(Collectors.toMap( + ModelConfigEntity::getModelName, + this::convertToData + )); + } + + @Override + @Transactional + public boolean deleteModelConfig(String modelName) { + log.debug("[MySQL] 删除模型配置: {}", modelName); + try { + modelConfigRepository.deleteByModelName(modelName); + log.info("[MySQL] 模型配置删除成功: {}", modelName); + return true; + } catch (Exception e) { + log.error("[MySQL] 删除模型配置失败: {}", modelName, e); + return false; + } + } + + @Override + public boolean existsModelConfig(String modelName) { + return modelConfigRepository.existsByModelName(modelName); + } + + @Override + public List getAllModelNames() { + return modelConfigRepository.findEnabledModelNames(); + } + + @Override + @Transactional + public void saveOperationConfig(String operationType, OperationConfigData config) { + log.debug("[MySQL] 保存操作配置: {}", operationType); + config.setOperationType(operationType); + + OperationConfigEntity entity = operationConfigRepository.findByOperationType(operationType) + .map(existing -> { + Long id = existing.getId(); + LocalDateTime createdAt = existing.getCreatedAt(); + + OperationConfigEntity updatedEntity = convertToEntity(config); + updatedEntity.setId(id); + updatedEntity.setCreatedAt(createdAt); + + return updatedEntity; + }) + .orElseGet(() -> convertToEntity(config)); + + operationConfigRepository.save(entity); + log.info("[MySQL] 操作配置保存成功: {}", operationType); + } + + @Override + public Optional getOperationConfig(String operationType) { + log.debug("[MySQL] 获取操作配置: {}", operationType); + return operationConfigRepository.findByOperationType(operationType) + .map(this::convertToData); + } + + @Override + public Map getAllOperationConfigs() { + log.debug("[MySQL] 获取所有操作配置"); + return operationConfigRepository.findAll().stream() + .collect(Collectors.toMap( + OperationConfigEntity::getOperationType, + this::convertToData + )); + } + + @Override + @Transactional + public boolean deleteOperationConfig(String operationType) { + log.debug("[MySQL] 删除操作配置: {}", operationType); + try { + operationConfigRepository.deleteByOperationType(operationType); + log.info("[MySQL] 操作配置删除成功: {}", operationType); + return true; + } catch (Exception e) { + log.error("[MySQL] 删除操作配置失败: {}", operationType, e); + return false; + } + } + + @Override + public void flush() { + log.debug("[MySQL] 刷新缓存"); + // MySQL特定的刷新逻辑 + } + + @Override + public void reload() { + log.debug("[MySQL] 重新加载配置"); + // MySQL特定的重载逻辑 + } + + @Override + @Transactional + public void backup(String backupName) { + log.info("[MySQL] 创建备份: {}", backupName); + // MySQL特定的备份实现 + // 可以使用CREATE TABLE ... AS SELECT语句 + } + + @Override + @Transactional + public void restoreFromBackup(String backupName) { + log.info("[MySQL] 从备份恢复: {}", backupName); + // MySQL特定的恢复实现 + } + + @Override + public List getAllBackupNames() { + log.debug("[MySQL] 获取所有备份名称"); + // 返回备份列表 + return List.of(); + } + + /** + * 将ModelConfigData转换为ModelConfigEntity + */ + private ModelConfigEntity convertToEntity(ModelConfigData data) { + ModelConfigEntity entity = new ModelConfigEntity(); + + // 映射基本字段 + entity.setModelName(data.getModelName()); + entity.setProvider(data.getProvider()); + entity.setApiKey(data.getApiKey()); + entity.setBaseUrl(data.getBaseUrl()); + entity.setEnabled(data.getEnabled()); + entity.setDescription(data.getDescription()); + + // 将扩展字段映射到customParams + Map customParams = new HashMap<>(); + if (data.getDefaultMaxTokens() != null) { + customParams.put("defaultMaxTokens", data.getDefaultMaxTokens()); + } + if (data.getDefaultTemperature() != null) { + customParams.put("defaultTemperature", data.getDefaultTemperature()); + } + if (data.getSupportStream() != null) { + customParams.put("supportStream", data.getSupportStream()); + } + if (data.getSupportJsonOutput() != null) { + customParams.put("supportJsonOutput", data.getSupportJsonOutput()); + } + if (data.getSupportThinking() != null) { + customParams.put("supportThinking", data.getSupportThinking()); + } + if (data.getAdditionalHeaders() != null && !data.getAdditionalHeaders().isEmpty()) { + customParams.put("additionalHeaders", data.getAdditionalHeaders()); + } + if (data.getCreatedAt() != null) { + customParams.put("createdAt", data.getCreatedAt()); + } + if (data.getUpdatedAt() != null) { + customParams.put("updatedAt", data.getUpdatedAt()); + } + + entity.setCustomParams(customParams); + return entity; + } + + /** + * 将ModelConfigEntity转换为ModelConfigData + */ + private ModelConfigData convertToData(ModelConfigEntity entity) { + ModelConfigData.ModelConfigDataBuilder builder = ModelConfigData.builder() + .modelName(entity.getModelName()) + .provider(entity.getProvider()) + .apiKey(entity.getApiKey()) + .baseUrl(entity.getBaseUrl()) + .enabled(entity.getEnabled()) + .description(entity.getDescription()); + + // 从customParams中提取扩展字段 + Map customParams = entity.getCustomParams(); + if (customParams != null) { + if (customParams.containsKey("defaultMaxTokens")) { + builder.defaultMaxTokens((Integer) customParams.get("defaultMaxTokens")); + } + if (customParams.containsKey("defaultTemperature")) { + builder.defaultTemperature((Double) customParams.get("defaultTemperature")); + } + if (customParams.containsKey("supportStream")) { + builder.supportStream((Boolean) customParams.get("supportStream")); + } + if (customParams.containsKey("supportJsonOutput")) { + builder.supportJsonOutput((Boolean) customParams.get("supportJsonOutput")); + } + if (customParams.containsKey("supportThinking")) { + builder.supportThinking((Boolean) customParams.get("supportThinking")); + } + if (customParams.containsKey("additionalHeaders")) { + @SuppressWarnings("unchecked") + Map headers = (Map) customParams.get("additionalHeaders"); + builder.additionalHeaders(headers != null ? headers : new HashMap<>()); + } + if (customParams.containsKey("createdAt")) { + builder.createdAt((Long) customParams.get("createdAt")); + } + if (customParams.containsKey("updatedAt")) { + builder.updatedAt((Long) customParams.get("updatedAt")); + } + } + + return builder.build(); + } + + /** + * 将OperationConfigData转换为OperationConfigEntity + */ + private OperationConfigEntity convertToEntity(OperationConfigData data) { + OperationConfigEntity entity = new OperationConfigEntity(); + entity.setOperationType(data.getOperationType()); + entity.setDescription(data.getDescription()); + entity.setEnabled(data.getEnabled()); + entity.setMaxTokens(data.getMaxTokens()); + entity.setTemperature(data.getTemperature()); + entity.setJsonOutput(data.getJsonOutput()); + entity.setThinkingMode(data.getThinkingMode()); + entity.setCustomParams(data.getCustomParams()); + entity.setModelName(data.getModelName()); + return entity; + } + + /** + * 将OperationConfigEntity转换为OperationConfigData + */ + private OperationConfigData convertToData(OperationConfigEntity entity) { + return OperationConfigData.builder() + .operationType(entity.getOperationType()) + .description(entity.getDescription()) + .enabled(entity.getEnabled()) + .maxTokens(entity.getMaxTokens()) + .temperature(entity.getTemperature()) + .jsonOutput(entity.getJsonOutput()) + .thinkingMode(entity.getThinkingMode()) + .customParams(entity.getCustomParams()) + .modelName(entity.getModelName()) + .build(); + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/OperationConfigData.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/OperationConfigData.java similarity index 98% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/OperationConfigData.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/OperationConfigData.java index 220b446..6e18d81 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/OperationConfigData.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/OperationConfigData.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence; +package com.suifeng.sfchain.persistence; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceManager.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceManager.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceManager.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceManager.java index e081e33..80b92ee 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceManager.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceManager.java @@ -1,10 +1,9 @@ -package io.github.timemachinelab.sfchain.persistence; +package com.suifeng.sfchain.persistence; -import io.github.timemachinelab.sfchain.core.AIOperationRegistry; -import io.github.timemachinelab.sfchain.core.ModelRegistry; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelConfig; -import io.github.timemachinelab.sfchain.core.openai.OpenAIModelFactory; -import lombok.RequiredArgsConstructor; +import com.suifeng.sfchain.core.AIOperationRegistry; +import com.suifeng.sfchain.core.ModelRegistry; +import com.suifeng.sfchain.core.openai.OpenAIModelConfig; +import com.suifeng.sfchain.core.openai.OpenAIModelFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; @@ -15,16 +14,8 @@ import java.util.Map; import java.util.Optional; -/** - * 描述: 持久化管理器 - * 负责协调持久化服务与现有的模型注册和操作注册系统 - * - * @author suifeng - * 日期: 2025/1/27 - */ @Slf4j @Component -@RequiredArgsConstructor public class PersistenceManager { private final PersistenceService persistenceService; @@ -33,6 +24,20 @@ public class PersistenceManager { private final OpenAIModelFactory modelFactory; private final DynamicOperationConfigService dynamicOperationConfigService; + // 统一使用构造函数注入 + public PersistenceManager( + PersistenceServiceFactory persistenceServiceFactory, + ModelRegistry modelRegistry, + AIOperationRegistry operationRegistry, + OpenAIModelFactory modelFactory, + DynamicOperationConfigService dynamicOperationConfigService) { + this.persistenceService = persistenceServiceFactory.createPersistenceService(); + this.modelRegistry = modelRegistry; + this.operationRegistry = operationRegistry; + this.modelFactory = modelFactory; + this.dynamicOperationConfigService = dynamicOperationConfigService; + } + /** * 应用启动完成后同步配置 */ @@ -666,4 +671,4 @@ private ModelConfigData convertFromOpenAIConfig(OpenAIModelConfig config) { data.updateTimestamp(); return data; } -} \ No newline at end of file +} diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceService.java similarity index 98% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceService.java index 3f9c7a5..37cd0b0 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PersistenceService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceService.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence; +package com.suifeng.sfchain.persistence; import java.util.List; import java.util.Map; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceServiceFactory.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceServiceFactory.java new file mode 100644 index 0000000..3805e94 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PersistenceServiceFactory.java @@ -0,0 +1,33 @@ +package com.suifeng.sfchain.persistence; + +import com.suifeng.sfchain.persistence.config.DatabaseType; +import com.suifeng.sfchain.persistence.config.PersistenceConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * 持久化服务工厂 + */ +@Component +public class PersistenceServiceFactory { + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private PersistenceConfig persistenceConfig; + + public PersistenceService createPersistenceService() { + DatabaseType dbType = persistenceConfig.getDatabaseTypeEnum(); + + switch (dbType) { + case MYSQL: + return applicationContext.getBean(MySQLPersistenceService.class); + case POSTGRESQL: + return applicationContext.getBean(PostgreSQLPersistenceService.class); + default: + throw new IllegalArgumentException("Unsupported database type: " + dbType); + } + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PostgreSQLPersistenceService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PostgreSQLPersistenceService.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PostgreSQLPersistenceService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PostgreSQLPersistenceService.java index 670b646..3fe64da 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/PostgreSQLPersistenceService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/PostgreSQLPersistenceService.java @@ -1,10 +1,11 @@ -package io.github.timemachinelab.sfchain.persistence; -import io.github.timemachinelab.sfchain.persistence.entity.ModelConfigEntity; -import io.github.timemachinelab.sfchain.persistence.entity.OperationConfigEntity; -import io.github.timemachinelab.sfchain.persistence.repository.ModelConfigRepository; -import io.github.timemachinelab.sfchain.persistence.repository.OperationConfigRepository; +package com.suifeng.sfchain.persistence; +import com.suifeng.sfchain.persistence.entity.ModelConfigEntity; +import com.suifeng.sfchain.persistence.entity.OperationConfigEntity; +import com.suifeng.sfchain.persistence.repository.ModelConfigRepository; +import com.suifeng.sfchain.persistence.repository.OperationConfigRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,6 +26,7 @@ @Slf4j @Service @RequiredArgsConstructor +@ConditionalOnProperty(name = "sf-chain.persistence.database-type", havingValue = "postgresql", matchIfMissing = true) public class PostgreSQLPersistenceService implements PersistenceService { private final ModelConfigRepository modelConfigRepository; diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/DatabaseType.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/DatabaseType.java new file mode 100644 index 0000000..1d4e1f0 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/DatabaseType.java @@ -0,0 +1,45 @@ +package com.suifeng.sfchain.persistence.config; + +/** + * 数据库类型枚举 + * + * @author suifeng + * 日期: 2025/1/27 + */ +public enum DatabaseType { + + MYSQL("mysql"), + POSTGRESQL("postgresql"); + + private final String value; + + DatabaseType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + /** + * 从字符串转换为枚举 + */ + public static DatabaseType fromString(String value) { + if (value == null) { + return MYSQL; // 默认值 + } + + for (DatabaseType type : DatabaseType.values()) { + if (type.value.equalsIgnoreCase(value)) { + return type; + } + } + + throw new IllegalArgumentException("不支持的数据库类型: " + value); + } + + @Override + public String toString() { + return value; + } +} \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/PersistenceConfig.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/PersistenceConfig.java new file mode 100644 index 0000000..d3a00c3 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/config/PersistenceConfig.java @@ -0,0 +1,29 @@ +package com.suifeng.sfchain.persistence.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 持久化配置类 + * + * @author suifeng + * 日期: 2025/1/27 + */ +@Data +@Component +@ConfigurationProperties(prefix = "sf-chain.persistence") +public class PersistenceConfig { + + /** + * 数据库类型,默认为MySQL + */ + private String databaseType = "mysql"; + + /** + * 获取数据库类型枚举 + */ + public DatabaseType getDatabaseTypeEnum() { + return DatabaseType.fromString(databaseType); + } +} \ No newline at end of file diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatContextService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatContextService.java similarity index 97% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatContextService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatContextService.java index cf6bec3..2a9f6ce 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatContextService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatContextService.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence.context; +package com.suifeng.sfchain.persistence.context; import java.util.List; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatMessage.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatMessage.java similarity index 96% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatMessage.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatMessage.java index 138b5d8..8cca1bb 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/ChatMessage.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/ChatMessage.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence.context; +package com.suifeng.sfchain.persistence.context; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/MapBasedChatContextService.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/MapBasedChatContextService.java similarity index 98% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/MapBasedChatContextService.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/MapBasedChatContextService.java index 29e4c3b..9195eeb 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/context/MapBasedChatContextService.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/context/MapBasedChatContextService.java @@ -1,4 +1,4 @@ -package io.github.timemachinelab.sfchain.persistence.context; +package com.suifeng.sfchain.persistence.context; import lombok.extern.slf4j.Slf4j; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/ModelConfigEntity.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/ModelConfigEntity.java similarity index 77% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/ModelConfigEntity.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/ModelConfigEntity.java index 1a9f024..9b8a4e0 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/ModelConfigEntity.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/ModelConfigEntity.java @@ -1,11 +1,13 @@ -package io.github.timemachinelab.sfchain.persistence.entity; +package com.suifeng.sfchain.persistence.entity; import com.vladmihalcea.hibernate.type.json.JsonBinaryType; +import com.vladmihalcea.hibernate.type.json.JsonType; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; import javax.persistence.*; import java.time.LocalDateTime; @@ -19,8 +21,11 @@ * 日期: 2025/1/27 */ @Entity -@Table(name = "ai_model_configs") -@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) +@Table(name = "sfchain_model_configs") +@TypeDefs({ + @TypeDef(name = "json", typeClass = JsonType.class), + @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) +}) @Data @NoArgsConstructor @AllArgsConstructor @@ -49,8 +54,9 @@ public class ModelConfigEntity { @Column(name = "description", length = 1000) private String description; - @Type(type = "jsonb") - @Column(name = "custom_params", columnDefinition = "jsonb") + // 使用固定的json类型,通过配置决定实际的数据库类型 + @Type(type = "json") + @Column(name = "custom_params", columnDefinition = "JSON") private Map customParams; @Column(name = "created_at", nullable = false) diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/OperationConfigEntity.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/OperationConfigEntity.java similarity index 79% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/OperationConfigEntity.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/OperationConfigEntity.java index 3edfe73..1eb83c5 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/entity/OperationConfigEntity.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/entity/OperationConfigEntity.java @@ -1,11 +1,13 @@ -package io.github.timemachinelab.sfchain.persistence.entity; +package com.suifeng.sfchain.persistence.entity; import com.vladmihalcea.hibernate.type.json.JsonBinaryType; +import com.vladmihalcea.hibernate.type.json.JsonType; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; import javax.persistence.*; import java.time.LocalDateTime; @@ -19,8 +21,11 @@ * 日期: 2025/1/27 */ @Entity -@Table(name = "ai_operation_configs") -@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) +@Table(name = "sfchain_operation_configs") +@TypeDefs({ + @TypeDef(name = "json", typeClass = JsonType.class), + @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) +}) @Data @NoArgsConstructor @AllArgsConstructor @@ -52,13 +57,11 @@ public class OperationConfigEntity { @Column(name = "thinking_mode", nullable = false) private Boolean thinkingMode = false; - @Type(type = "jsonb") - @Column(name = "custom_params", columnDefinition = "jsonb") + // 使用固定的json类型,通过配置决定实际的数据库类型 + @Type(type = "json") + @Column(name = "custom_params", columnDefinition = "JSON") private Map customParams; - /** - * 关联的模型名称 - */ @Column(name = "model_name", length = 100) private String modelName; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/ModelConfigRepository.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/ModelConfigRepository.java similarity index 92% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/ModelConfigRepository.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/ModelConfigRepository.java index 0f71087..1e60944 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/ModelConfigRepository.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/ModelConfigRepository.java @@ -1,6 +1,6 @@ -package io.github.timemachinelab.sfchain.persistence.repository; +package com.suifeng.sfchain.persistence.repository; -import io.github.timemachinelab.sfchain.persistence.entity.ModelConfigEntity; +import com.suifeng.sfchain.persistence.entity.ModelConfigEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/OperationConfigRepository.java b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/OperationConfigRepository.java similarity index 93% rename from prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/OperationConfigRepository.java rename to prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/OperationConfigRepository.java index aa911bc..0829317 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/persistence/repository/OperationConfigRepository.java +++ b/prompto-lab-app/SF-Chain/src/main/java/com/suifeng/sfchain/persistence/repository/OperationConfigRepository.java @@ -1,6 +1,6 @@ -package io.github.timemachinelab.sfchain.persistence.repository; +package com.suifeng.sfchain.persistence.repository; -import io.github.timemachinelab.sfchain.persistence.entity.OperationConfigEntity; +import com.suifeng.sfchain.persistence.entity.OperationConfigEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; diff --git a/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring.factories b/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..5ea5318 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Auto Configuration +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.suifeng.sfchain.config.SfChainAutoConfiguration \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..3255854 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.suifeng.sfchain.config.SfChainAutoConfiguration \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/migration/v1_mysql.sql b/prompto-lab-app/SF-Chain/src/main/resources/migration/v1_mysql.sql new file mode 100644 index 0000000..9832f42 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/migration/v1_mysql.sql @@ -0,0 +1,63 @@ +-- 创建AI相关数据表 (MySQL版本) +-- 作者: suifeng +-- 日期: 2025/1/27 + +-- 创建模型配置表 +CREATE TABLE IF NOT EXISTS sfchain_model_configs ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + model_name VARCHAR(100) NOT NULL UNIQUE, + provider VARCHAR(50) NOT NULL, + api_key VARCHAR(500), + base_url VARCHAR(500), + enabled BOOLEAN NOT NULL DEFAULT true, + description VARCHAR(1000), + custom_params JSON, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 创建操作配置表(直接包含模型名称字段) +CREATE TABLE IF NOT EXISTS sfchain_operation_configs ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + operation_type VARCHAR(100) NOT NULL UNIQUE, + description VARCHAR(1000), + enabled BOOLEAN NOT NULL DEFAULT true, + max_tokens INTEGER, + temperature DOUBLE, + json_output BOOLEAN NOT NULL DEFAULT false, + thinking_mode BOOLEAN NOT NULL DEFAULT false, + custom_params JSON, + model_name VARCHAR(100), -- 直接在操作配置表中存储关联的模型名称 + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 创建索引 +CREATE INDEX idx_sfchain_model_configs_model_name ON sfchain_model_configs(model_name); +CREATE INDEX idx_sfchain_model_configs_provider ON sfchain_model_configs(provider); +CREATE INDEX idx_sfchain_model_configs_enabled ON sfchain_model_configs(enabled); +CREATE INDEX idx_sfchain_operation_configs_operation_type ON sfchain_operation_configs(operation_type); +CREATE INDEX idx_sfchain_operation_configs_enabled ON sfchain_operation_configs(enabled); +CREATE INDEX idx_sfchain_operation_configs_model ON sfchain_operation_configs(model_name); + +-- 添加外键约束 +ALTER TABLE sfchain_operation_configs + ADD CONSTRAINT fk_operation_model + FOREIGN KEY (model_name) REFERENCES sfchain_model_configs(model_name) + ON DELETE SET NULL; + +-- 仅在表为空时插入示例数据 +INSERT INTO sfchain_model_configs (model_name, provider, enabled, description) +SELECT * FROM ( + SELECT 'deepseek-chat' as model_name, 'deepseek' as provider, true as enabled, 'DeepSeek Chat模型' as description + UNION ALL + SELECT 'gpt-4o', 'openai', true, 'OpenAI GPT-4o模型' + UNION ALL + SELECT 'siliconflow-qwen', 'siliconflow', true, 'SiliconFlow Qwen模型' +) AS tmp +WHERE NOT EXISTS ( + SELECT 1 FROM sfchain_model_configs LIMIT 1 +); + +-- 提交事务 +COMMIT; \ No newline at end of file diff --git a/prompto-lab-app/src/main/resources/db/migration/V1__Create_AI_Tables.sql b/prompto-lab-app/SF-Chain/src/main/resources/migration/v1_postgresql.sql similarity index 61% rename from prompto-lab-app/src/main/resources/db/migration/V1__Create_AI_Tables.sql rename to prompto-lab-app/SF-Chain/src/main/resources/migration/v1_postgresql.sql index bc8fb9b..4fa4f01 100644 --- a/prompto-lab-app/src/main/resources/db/migration/V1__Create_AI_Tables.sql +++ b/prompto-lab-app/SF-Chain/src/main/resources/migration/v1_postgresql.sql @@ -3,7 +3,7 @@ -- 日期: 2025/1/27 -- 创建模型配置表 -CREATE TABLE IF NOT EXISTS ai_model_configs ( +CREATE TABLE IF NOT EXISTS sfchain_model_configs ( id BIGSERIAL PRIMARY KEY, model_name VARCHAR(100) NOT NULL UNIQUE, provider VARCHAR(50) NOT NULL, @@ -17,7 +17,7 @@ CREATE TABLE IF NOT EXISTS ai_model_configs ( ); -- 创建操作配置表(直接包含模型名称字段) -CREATE TABLE IF NOT EXISTS ai_operation_configs ( +CREATE TABLE IF NOT EXISTS sfchain_operation_configs ( id BIGSERIAL PRIMARY KEY, operation_type VARCHAR(100) NOT NULL UNIQUE, description VARCHAR(1000), @@ -33,17 +33,17 @@ CREATE TABLE IF NOT EXISTS ai_operation_configs ( ); -- 创建索引 -CREATE INDEX IF NOT EXISTS idx_model_configs_model_name ON ai_model_configs(model_name); -CREATE INDEX IF NOT EXISTS idx_model_configs_provider ON ai_model_configs(provider); -CREATE INDEX IF NOT EXISTS idx_model_configs_enabled ON ai_model_configs(enabled); -CREATE INDEX IF NOT EXISTS idx_operation_configs_operation_type ON ai_operation_configs(operation_type); -CREATE INDEX IF NOT EXISTS idx_operation_configs_enabled ON ai_operation_configs(enabled); -CREATE INDEX IF NOT EXISTS idx_operation_configs_model ON ai_operation_configs(model_name); +CREATE INDEX IF NOT EXISTS idx_sfchain_model_configs_model_name ON sfchain_model_configs(model_name); +CREATE INDEX IF NOT EXISTS idx_sfchain_model_configs_provider ON sfchain_model_configs(provider); +CREATE INDEX IF NOT EXISTS idx_sfchain_model_configs_enabled ON sfchain_model_configs(enabled); +CREATE INDEX IF NOT EXISTS idx_sfchain_operation_configs_operation_type ON sfchain_operation_configs(operation_type); +CREATE INDEX IF NOT EXISTS idx_sfchain_operation_configs_enabled ON sfchain_operation_configs(enabled); +CREATE INDEX IF NOT EXISTS idx_sfchain_operation_configs_model ON sfchain_operation_configs(model_name); -- 添加外键约束 -ALTER TABLE ai_operation_configs +ALTER TABLE sfchain_operation_configs ADD CONSTRAINT fk_operation_model - FOREIGN KEY (model_name) REFERENCES ai_model_configs(model_name) + FOREIGN KEY (model_name) REFERENCES sfchain_model_configs(model_name) ON DELETE SET NULL; -- 创建更新时间戳的触发器函数 @@ -56,16 +56,16 @@ END; $$ language 'plpgsql'; -- 为每个表创建更新时间戳触发器 -CREATE TRIGGER update_ai_model_configs_updated_at - BEFORE UPDATE ON ai_model_configs +CREATE TRIGGER update_sfchain_model_configs_updated_at + BEFORE UPDATE ON sfchain_model_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -CREATE TRIGGER update_ai_operation_configs_updated_at - BEFORE UPDATE ON ai_operation_configs +CREATE TRIGGER update_sfchain_operation_configs_updated_at + BEFORE UPDATE ON sfchain_operation_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- 插入一些示例数据 -INSERT INTO ai_model_configs (model_name, provider, enabled, description) VALUES +INSERT INTO sfchain_model_configs (model_name, provider, enabled, description) VALUES ('deepseek-chat', 'deepseek', true, 'DeepSeek Chat模型'), ('gpt-4o', 'openai', true, 'OpenAI GPT-4o模型'), ('siliconflow-qwen', 'siliconflow', true, 'SiliconFlow Qwen模型') diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-Cp61OaZJ.js b/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-Cp61OaZJ.js new file mode 100644 index 0000000..0072f37 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-Cp61OaZJ.js @@ -0,0 +1,75 @@ +var Sl=Object.defineProperty;var Tl=(e,t,s)=>t in e?Sl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s;var gs=(e,t,s)=>Tl(e,typeof t!="symbol"?t+"":t,s);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const l of r.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&n(l)}).observe(document,{childList:!0,subtree:!0});function s(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function n(o){if(o.ep)return;o.ep=!0;const r=s(o);fetch(o.href,r)}})();/** +* @vue/shared v3.5.17 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function vo(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const we={},ns=[],ot=()=>{},El=()=>!1,bn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),go=e=>e.startsWith("onUpdate:"),Re=Object.assign,mo=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},Al=Object.prototype.hasOwnProperty,he=(e,t)=>Al.call(e,t),ee=Array.isArray,os=e=>zs(e)==="[object Map]",ps=e=>zs(e)==="[object Set]",Uo=e=>zs(e)==="[object Date]",ie=e=>typeof e=="function",Te=e=>typeof e=="string",gt=e=>typeof e=="symbol",ke=e=>e!==null&&typeof e=="object",Kr=e=>(ke(e)||ie(e))&&ie(e.then)&&ie(e.catch),zr=Object.prototype.toString,zs=e=>zr.call(e),Ml=e=>zs(e).slice(8,-1),Gr=e=>zs(e)==="[object Object]",yo=e=>Te(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,xs=vo(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),_n=e=>{const t=Object.create(null);return s=>t[s]||(t[s]=e(s))},Ol=/-(\w)/g,nt=_n(e=>e.replace(Ol,(t,s)=>s?s.toUpperCase():"")),Pl=/\B([A-Z])/g,Ht=_n(e=>e.replace(Pl,"-$1").toLowerCase()),wn=_n(e=>e.charAt(0).toUpperCase()+e.slice(1)),Rn=_n(e=>e?`on${wn(e)}`:""),Nt=(e,t)=>!Object.is(e,t),sn=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},cn=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Rl=e=>{const t=Te(e)?Number(e):NaN;return isNaN(t)?e:t};let Ho;const kn=()=>Ho||(Ho=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Ns(e){if(ee(e)){const t={};for(let s=0;s{if(s){const n=s.split(Il);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function be(e){let t="";if(Te(e))t=e;else if(ee(e))for(let s=0;sYt(s,t))}const Wr=e=>!!(e&&e.__v_isRef===!0),U=e=>Te(e)?e:e==null?"":ee(e)||ke(e)&&(e.toString===zr||!ie(e.toString))?Wr(e)?U(e.value):JSON.stringify(e,Qr,2):String(e),Qr=(e,t)=>Wr(t)?Qr(e,t.value):os(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,o],r)=>(s[Ln(n,r)+" =>"]=o,s),{})}:ps(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>Ln(s))}:gt(t)?Ln(t):ke(t)&&!ee(t)&&!Gr(t)?String(t):t,Ln=(e,t="")=>{var s;return gt(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/** +* @vue/reactivity v3.5.17 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Je;class Yr{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=Je,!t&&Je&&(this.index=(Je.scopes||(Je.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t0&&--this._on===0&&(Je=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s0)return;if($s){let t=$s;for($s=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;Cs;){let t=Cs;for(Cs=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function ti(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function si(e){let t,s=e.depsTail,n=s;for(;n;){const o=n.prevDep;n.version===-1?(n===s&&(s=o),ko(n),Fl(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=o}e.deps=t,e.depsTail=s}function Qn(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(ni(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function ni(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===js)||(e.globalVersion=js,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Qn(e))))return;e.flags|=2;const t=e.dep,s=Ce,n=rt;Ce=e,rt=!0;try{ti(e);const o=e.fn(e._value);(t.version===0||Nt(o,e._value))&&(e.flags|=128,e._value=o,t.version++)}catch(o){throw t.version++,o}finally{Ce=s,rt=n,si(e),e.flags&=-3}}function ko(e,t=!1){const{dep:s,prevSub:n,nextSub:o}=e;if(n&&(n.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let r=s.computed.deps;r;r=r.nextDep)ko(r,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function Fl(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let rt=!0;const oi=[];function St(){oi.push(rt),rt=!1}function Tt(){const e=oi.pop();rt=e===void 0?!0:e}function Do(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=Ce;Ce=void 0;try{t()}finally{Ce=s}}}let js=0;class ql{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class xo{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Ce||!rt||Ce===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==Ce)s=this.activeLink=new ql(Ce,this),Ce.deps?(s.prevDep=Ce.depsTail,Ce.depsTail.nextDep=s,Ce.depsTail=s):Ce.deps=Ce.depsTail=s,ri(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=Ce.depsTail,s.nextDep=void 0,Ce.depsTail.nextDep=s,Ce.depsTail=s,Ce.deps===s&&(Ce.deps=n)}return s}trigger(t){this.version++,js++,this.notify(t)}notify(t){_o();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{wo()}}}function ri(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)ri(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const Yn=new WeakMap,Wt=Symbol(""),Zn=Symbol(""),Bs=Symbol("");function je(e,t,s){if(rt&&Ce){let n=Yn.get(e);n||Yn.set(e,n=new Map);let o=n.get(s);o||(n.set(s,o=new xo),o.map=n,o.key=s),o.track()}}function kt(e,t,s,n,o,r){const l=Yn.get(e);if(!l){js++;return}const a=c=>{c&&c.trigger()};if(_o(),t==="clear")l.forEach(a);else{const c=ee(e),d=c&&yo(s);if(c&&s==="length"){const u=Number(n);l.forEach((f,v)=>{(v==="length"||v===Bs||!gt(v)&&v>=u)&&a(f)})}else switch((s!==void 0||l.has(void 0))&&a(l.get(s)),d&&a(l.get(Bs)),t){case"add":c?d&&a(l.get("length")):(a(l.get(Wt)),os(e)&&a(l.get(Zn)));break;case"delete":c||(a(l.get(Wt)),os(e)&&a(l.get(Zn)));break;case"set":os(e)&&a(l.get(Wt));break}}wo()}function Xt(e){const t=fe(e);return t===e?t:(je(t,"iterate",Bs),tt(e)?t:t.map(Ie))}function xn(e){return je(e=fe(e),"iterate",Bs),e}const Kl={__proto__:null,[Symbol.iterator](){return Nn(this,Symbol.iterator,Ie)},concat(...e){return Xt(this).concat(...e.map(t=>ee(t)?Xt(t):t))},entries(){return Nn(this,"entries",e=>(e[1]=Ie(e[1]),e))},every(e,t){return mt(this,"every",e,t,void 0,arguments)},filter(e,t){return mt(this,"filter",e,t,s=>s.map(Ie),arguments)},find(e,t){return mt(this,"find",e,t,Ie,arguments)},findIndex(e,t){return mt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return mt(this,"findLast",e,t,Ie,arguments)},findLastIndex(e,t){return mt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return mt(this,"forEach",e,t,void 0,arguments)},includes(...e){return jn(this,"includes",e)},indexOf(...e){return jn(this,"indexOf",e)},join(e){return Xt(this).join(e)},lastIndexOf(...e){return jn(this,"lastIndexOf",e)},map(e,t){return mt(this,"map",e,t,void 0,arguments)},pop(){return ms(this,"pop")},push(...e){return ms(this,"push",e)},reduce(e,...t){return Vo(this,"reduce",e,t)},reduceRight(e,...t){return Vo(this,"reduceRight",e,t)},shift(){return ms(this,"shift")},some(e,t){return mt(this,"some",e,t,void 0,arguments)},splice(...e){return ms(this,"splice",e)},toReversed(){return Xt(this).toReversed()},toSorted(e){return Xt(this).toSorted(e)},toSpliced(...e){return Xt(this).toSpliced(...e)},unshift(...e){return ms(this,"unshift",e)},values(){return Nn(this,"values",Ie)}};function Nn(e,t,s){const n=xn(e),o=n[t]();return n!==e&&!tt(e)&&(o._next=o.next,o.next=()=>{const r=o._next();return r.value&&(r.value=s(r.value)),r}),o}const zl=Array.prototype;function mt(e,t,s,n,o,r){const l=xn(e),a=l!==e&&!tt(e),c=l[t];if(c!==zl[t]){const f=c.apply(e,r);return a?Ie(f):f}let d=s;l!==e&&(a?d=function(f,v){return s.call(this,Ie(f),v,e)}:s.length>2&&(d=function(f,v){return s.call(this,f,v,e)}));const u=c.call(l,d,n);return a&&o?o(u):u}function Vo(e,t,s,n){const o=xn(e);let r=s;return o!==e&&(tt(e)?s.length>3&&(r=function(l,a,c){return s.call(this,l,a,c,e)}):r=function(l,a,c){return s.call(this,l,Ie(a),c,e)}),o[t](r,...n)}function jn(e,t,s){const n=fe(e);je(n,"iterate",Bs);const o=n[t](...s);return(o===-1||o===!1)&&So(s[0])?(s[0]=fe(s[0]),n[t](...s)):o}function ms(e,t,s=[]){St(),_o();const n=fe(e)[t].apply(e,s);return wo(),Tt(),n}const Gl=vo("__proto__,__v_isRef,__isVue"),ii=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(gt));function Jl(e){gt(e)||(e=String(e));const t=fe(this);return je(t,"has",e),t.hasOwnProperty(e)}class li{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const o=this._isReadonly,r=this._isShallow;if(s==="__v_isReactive")return!o;if(s==="__v_isReadonly")return o;if(s==="__v_isShallow")return r;if(s==="__v_raw")return n===(o?r?oa:di:r?ui:ci).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const l=ee(t);if(!o){let c;if(l&&(c=Kl[s]))return c;if(s==="hasOwnProperty")return Jl}const a=Reflect.get(t,s,Ue(t)?t:n);return(gt(s)?ii.has(s):Gl(s))||(o||je(t,"get",s),r)?a:Ue(a)?l&&yo(s)?a:a.value:ke(a)?o?pi(a):hs(a):a}}class ai extends li{constructor(t=!1){super(!1,t)}set(t,s,n,o){let r=t[s];if(!this._isShallow){const c=jt(r);if(!tt(n)&&!jt(n)&&(r=fe(r),n=fe(n)),!ee(t)&&Ue(r)&&!Ue(n))return c?!1:(r.value=n,!0)}const l=ee(t)&&yo(s)?Number(s)e,Ws=e=>Reflect.getPrototypeOf(e);function Xl(e,t,s){return function(...n){const o=this.__v_raw,r=fe(o),l=os(r),a=e==="entries"||e===Symbol.iterator&&l,c=e==="keys"&&l,d=o[e](...n),u=s?Xn:t?un:Ie;return!t&&je(r,"iterate",c?Zn:Wt),{next(){const{value:f,done:v}=d.next();return v?{value:f,done:v}:{value:a?[u(f[0]),u(f[1])]:u(f),done:v}},[Symbol.iterator](){return this}}}}function Qs(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ea(e,t){const s={get(o){const r=this.__v_raw,l=fe(r),a=fe(o);e||(Nt(o,a)&&je(l,"get",o),je(l,"get",a));const{has:c}=Ws(l),d=t?Xn:e?un:Ie;if(c.call(l,o))return d(r.get(o));if(c.call(l,a))return d(r.get(a));r!==l&&r.get(o)},get size(){const o=this.__v_raw;return!e&&je(fe(o),"iterate",Wt),Reflect.get(o,"size",o)},has(o){const r=this.__v_raw,l=fe(r),a=fe(o);return e||(Nt(o,a)&&je(l,"has",o),je(l,"has",a)),o===a?r.has(o):r.has(o)||r.has(a)},forEach(o,r){const l=this,a=l.__v_raw,c=fe(a),d=t?Xn:e?un:Ie;return!e&&je(c,"iterate",Wt),a.forEach((u,f)=>o.call(r,d(u),d(f),l))}};return Re(s,e?{add:Qs("add"),set:Qs("set"),delete:Qs("delete"),clear:Qs("clear")}:{add(o){!t&&!tt(o)&&!jt(o)&&(o=fe(o));const r=fe(this);return Ws(r).has.call(r,o)||(r.add(o),kt(r,"add",o,o)),this},set(o,r){!t&&!tt(r)&&!jt(r)&&(r=fe(r));const l=fe(this),{has:a,get:c}=Ws(l);let d=a.call(l,o);d||(o=fe(o),d=a.call(l,o));const u=c.call(l,o);return l.set(o,r),d?Nt(r,u)&&kt(l,"set",o,r):kt(l,"add",o,r),this},delete(o){const r=fe(this),{has:l,get:a}=Ws(r);let c=l.call(r,o);c||(o=fe(o),c=l.call(r,o)),a&&a.call(r,o);const d=r.delete(o);return c&&kt(r,"delete",o,void 0),d},clear(){const o=fe(this),r=o.size!==0,l=o.clear();return r&&kt(o,"clear",void 0,void 0),l}}),["keys","values","entries",Symbol.iterator].forEach(o=>{s[o]=Xl(o,e,t)}),s}function Co(e,t){const s=ea(e,t);return(n,o,r)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?n:Reflect.get(he(s,o)&&o in n?s:n,o,r)}const ta={get:Co(!1,!1)},sa={get:Co(!1,!0)},na={get:Co(!0,!1)};const ci=new WeakMap,ui=new WeakMap,di=new WeakMap,oa=new WeakMap;function ra(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ia(e){return e.__v_skip||!Object.isExtensible(e)?0:ra(Ml(e))}function hs(e){return jt(e)?e:$o(e,!1,Ql,ta,ci)}function fi(e){return $o(e,!1,Zl,sa,ui)}function pi(e){return $o(e,!0,Yl,na,di)}function $o(e,t,s,n,o){if(!ke(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=ia(e);if(r===0)return e;const l=o.get(e);if(l)return l;const a=new Proxy(e,r===2?n:s);return o.set(e,a),a}function rs(e){return jt(e)?rs(e.__v_raw):!!(e&&e.__v_isReactive)}function jt(e){return!!(e&&e.__v_isReadonly)}function tt(e){return!!(e&&e.__v_isShallow)}function So(e){return e?!!e.__v_raw:!1}function fe(e){const t=e&&e.__v_raw;return t?fe(t):e}function hi(e){return!he(e,"__v_skip")&&Object.isExtensible(e)&&Wn(e,"__v_skip",!0),e}const Ie=e=>ke(e)?hs(e):e,un=e=>ke(e)?pi(e):e;function Ue(e){return e?e.__v_isRef===!0:!1}function Z(e){return vi(e,!1)}function la(e){return vi(e,!0)}function vi(e,t){return Ue(e)?e:new aa(e,t)}class aa{constructor(t,s){this.dep=new xo,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:fe(t),this._value=s?t:Ie(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||tt(t)||jt(t);t=n?t:fe(t),Nt(t,s)&&(this._rawValue=t,this._value=n?t:Ie(t),this.dep.trigger())}}function Ee(e){return Ue(e)?e.value:e}const ca={get:(e,t,s)=>t==="__v_raw"?e:Ee(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const o=e[t];return Ue(o)&&!Ue(s)?(o.value=s,!0):Reflect.set(e,t,s,n)}};function gi(e){return rs(e)?e:new Proxy(e,ca)}class ua{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new xo(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=js-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&Ce!==this)return ei(this,!0),!0}get value(){const t=this.dep.track();return ni(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function da(e,t,s=!1){let n,o;return ie(e)?n=e:(n=e.get,o=e.set),new ua(n,o,s)}const Ys={},dn=new WeakMap;let zt;function fa(e,t=!1,s=zt){if(s){let n=dn.get(s);n||dn.set(s,n=[]),n.push(e)}}function pa(e,t,s=we){const{immediate:n,deep:o,once:r,scheduler:l,augmentJob:a,call:c}=s,d=y=>o?y:tt(y)||o===!1||o===0?xt(y,1):xt(y);let u,f,v,g,x=!1,L=!1;if(Ue(e)?(f=()=>e.value,x=tt(e)):rs(e)?(f=()=>d(e),x=!0):ee(e)?(L=!0,x=e.some(y=>rs(y)||tt(y)),f=()=>e.map(y=>{if(Ue(y))return y.value;if(rs(y))return d(y);if(ie(y))return c?c(y,2):y()})):ie(e)?t?f=c?()=>c(e,2):e:f=()=>{if(v){St();try{v()}finally{Tt()}}const y=zt;zt=u;try{return c?c(e,3,[g]):e(g)}finally{zt=y}}:f=ot,t&&o){const y=f,P=o===!0?1/0:o;f=()=>xt(y(),P)}const J=Vl(),j=()=>{u.stop(),J&&J.active&&mo(J.effects,u)};if(r&&t){const y=t;t=(...P)=>{y(...P),j()}}let V=L?new Array(e.length).fill(Ys):Ys;const T=y=>{if(!(!(u.flags&1)||!u.dirty&&!y))if(t){const P=u.run();if(o||x||(L?P.some((I,C)=>Nt(I,V[C])):Nt(P,V))){v&&v();const I=zt;zt=u;try{const C=[P,V===Ys?void 0:L&&V[0]===Ys?[]:V,g];V=P,c?c(t,3,C):t(...C)}finally{zt=I}}}else u.run()};return a&&a(T),u=new Zr(f),u.scheduler=l?()=>l(T,!1):T,g=y=>fa(y,!1,u),v=u.onStop=()=>{const y=dn.get(u);if(y){if(c)c(y,4);else for(const P of y)P();dn.delete(u)}},t?n?T(!0):V=u.run():l?l(T.bind(null,!0),!0):u.run(),j.pause=u.pause.bind(u),j.resume=u.resume.bind(u),j.stop=j,j}function xt(e,t=1/0,s){if(t<=0||!ke(e)||e.__v_skip||(s=s||new Set,s.has(e)))return e;if(s.add(e),t--,Ue(e))xt(e.value,t,s);else if(ee(e))for(let n=0;n{xt(n,t,s)});else if(Gr(e)){for(const n in e)xt(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&&xt(e[n],t,s)}return e}/** +* @vue/runtime-core v3.5.17 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Gs(e,t,s,n){try{return n?e(...n):e()}catch(o){Cn(o,t,s)}}function it(e,t,s,n){if(ie(e)){const o=Gs(e,t,s,n);return o&&Kr(o)&&o.catch(r=>{Cn(r,t,s)}),o}if(ee(e)){const o=[];for(let r=0;r>>1,o=Fe[n],r=Us(o);r=Us(s)?Fe.push(e):Fe.splice(va(t),0,e),e.flags|=1,yi()}}function yi(){fn||(fn=mi.then(wi))}function bi(e){ee(e)?is.push(...e):Pt&&e.id===-1?Pt.splice(ts+1,0,e):e.flags&1||(is.push(e),e.flags|=1),yi()}function Fo(e,t,s=pt+1){for(;sUs(s)-Us(n));if(is.length=0,Pt){Pt.push(...t);return}for(Pt=t,ts=0;tse.id==null?e.flags&2?-1:1/0:e.id;function wi(e){try{for(pt=0;pt{n._d&&nr(-1);const r=pn(t);let l;try{l=e(...o)}finally{pn(r),n._d&&nr(1)}return l};return n._n=!0,n._c=!0,n._d=!0,n}function $e(e,t){if(Qe===null)return e;const s=On(Qe),n=e.dirs||(e.dirs=[]);for(let o=0;oe.__isTeleport,Ss=e=>e&&(e.disabled||e.disabled===""),qo=e=>e&&(e.defer||e.defer===""),Ko=e=>typeof SVGElement<"u"&&e instanceof SVGElement,zo=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,eo=(e,t)=>{const s=e&&e.to;return Te(s)?t?t(s):null:s},Si={name:"Teleport",__isTeleport:!0,process(e,t,s,n,o,r,l,a,c,d){const{mc:u,pc:f,pbc:v,o:{insert:g,querySelector:x,createText:L,createComment:J}}=d,j=Ss(t.props);let{shapeFlag:V,children:T,dynamicChildren:y}=t;if(e==null){const P=t.el=L(""),I=t.anchor=L("");g(P,s,n),g(I,s,n);const C=(O,W)=>{V&16&&(o&&o.isCE&&(o.ce._teleportTarget=O),u(T,O,W,o,r,l,a,c))},$=()=>{const O=t.target=eo(t.props,x),W=Ti(O,t,L,g);O&&(l!=="svg"&&Ko(O)?l="svg":l!=="mathml"&&zo(O)&&(l="mathml"),j||(C(O,W),nn(t,!1)))};j&&(C(s,I),nn(t,!0)),qo(t.props)?(t.el.__isMounted=!1,Ve(()=>{$(),delete t.el.__isMounted},r)):$()}else{if(qo(t.props)&&e.el.__isMounted===!1){Ve(()=>{Si.process(e,t,s,n,o,r,l,a,c,d)},r);return}t.el=e.el,t.targetStart=e.targetStart;const P=t.anchor=e.anchor,I=t.target=e.target,C=t.targetAnchor=e.targetAnchor,$=Ss(e.props),O=$?s:I,W=$?P:C;if(l==="svg"||Ko(I)?l="svg":(l==="mathml"||zo(I))&&(l="mathml"),y?(v(e.dynamicChildren,y,O,o,r,l,a),Mo(e,t,!0)):c||f(e,t,O,W,o,r,l,a,!1),j)$?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):Zs(t,s,P,d,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const te=t.target=eo(t.props,x);te&&Zs(t,te,null,d,0)}else $&&Zs(t,I,C,d,1);nn(t,j)}},remove(e,t,s,{um:n,o:{remove:o}},r){const{shapeFlag:l,children:a,anchor:c,targetStart:d,targetAnchor:u,target:f,props:v}=e;if(f&&(o(d),o(u)),r&&o(c),l&16){const g=r||!Ss(v);for(let x=0;x{e.isMounted=!0}),Ni(()=>{e.isUnmounting=!0}),e}const et=[Function,Array],Ei={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:et,onEnter:et,onAfterEnter:et,onEnterCancelled:et,onBeforeLeave:et,onLeave:et,onAfterLeave:et,onLeaveCancelled:et,onBeforeAppear:et,onAppear:et,onAfterAppear:et,onAppearCancelled:et},Ai=e=>{const t=e.subTree;return t.component?Ai(t.component):t},ba={name:"BaseTransition",props:Ei,setup(e,{slots:t}){const s=sl(),n=ya();return()=>{const o=t.default&&Pi(t.default(),!0);if(!o||!o.length)return;const r=Mi(o),l=fe(e),{mode:a}=l;if(n.isLeaving)return Bn(r);const c=Go(r);if(!c)return Bn(r);let d=to(c,l,n,s,f=>d=f);c.type!==Ke&&Hs(c,d);let u=s.subTree&&Go(s.subTree);if(u&&u.type!==Ke&&!Gt(c,u)&&Ai(s).type!==Ke){let f=to(u,l,n,s);if(Hs(u,f),a==="out-in"&&c.type!==Ke)return n.isLeaving=!0,f.afterLeave=()=>{n.isLeaving=!1,s.job.flags&8||s.update(),delete f.afterLeave,u=void 0},Bn(r);a==="in-out"&&c.type!==Ke?f.delayLeave=(v,g,x)=>{const L=Oi(n,u);L[String(u.key)]=u,v[Rt]=()=>{g(),v[Rt]=void 0,delete d.delayedLeave,u=void 0},d.delayedLeave=()=>{x(),delete d.delayedLeave,u=void 0}}:u=void 0}else u&&(u=void 0);return r}}};function Mi(e){let t=e[0];if(e.length>1){for(const s of e)if(s.type!==Ke){t=s;break}}return t}const _a=ba;function Oi(e,t){const{leavingVNodes:s}=e;let n=s.get(t.type);return n||(n=Object.create(null),s.set(t.type,n)),n}function to(e,t,s,n,o){const{appear:r,mode:l,persisted:a=!1,onBeforeEnter:c,onEnter:d,onAfterEnter:u,onEnterCancelled:f,onBeforeLeave:v,onLeave:g,onAfterLeave:x,onLeaveCancelled:L,onBeforeAppear:J,onAppear:j,onAfterAppear:V,onAppearCancelled:T}=t,y=String(e.key),P=Oi(s,e),I=(O,W)=>{O&&it(O,n,9,W)},C=(O,W)=>{const te=W[1];I(O,W),ee(O)?O.every(k=>k.length<=1)&&te():O.length<=1&&te()},$={mode:l,persisted:a,beforeEnter(O){let W=c;if(!s.isMounted)if(r)W=J||c;else return;O[Rt]&&O[Rt](!0);const te=P[y];te&&Gt(e,te)&&te.el[Rt]&&te.el[Rt](),I(W,[O])},enter(O){let W=d,te=u,k=f;if(!s.isMounted)if(r)W=j||d,te=V||u,k=T||f;else return;let _=!1;const B=O[Xs]=ne=>{_||(_=!0,ne?I(k,[O]):I(te,[O]),$.delayedLeave&&$.delayedLeave(),O[Xs]=void 0)};W?C(W,[O,B]):B()},leave(O,W){const te=String(e.key);if(O[Xs]&&O[Xs](!0),s.isUnmounting)return W();I(v,[O]);let k=!1;const _=O[Rt]=B=>{k||(k=!0,W(),B?I(L,[O]):I(x,[O]),O[Rt]=void 0,P[te]===e&&delete P[te])};P[te]=e,g?C(g,[O,_]):_()},clone(O){const W=to(O,t,s,n,o);return o&&o(W),W}};return $}function Bn(e){if(Sn(e))return e=Bt(e),e.children=null,e}function Go(e){if(!Sn(e))return $i(e.type)&&e.children?Mi(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:s}=e;if(s){if(t&16)return s[0];if(t&32&&ie(s.default))return s.default()}}function Hs(e,t){e.shapeFlag&6&&e.component?(e.transition=t,Hs(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Pi(e,t=!1,s){let n=[],o=0;for(let r=0;r1)for(let r=0;rTs(x,t&&(ee(t)?t[L]:t),s,n,o));return}if(Es(n)&&!o){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&Ts(e,t,s,n.component.subTree);return}const r=n.shapeFlag&4?On(n.component):n.el,l=o?null:r,{i:a,r:c}=e,d=t&&t.r,u=a.refs===we?a.refs={}:a.refs,f=a.setupState,v=fe(f),g=f===we?()=>!1:x=>he(v,x);if(d!=null&&d!==c&&(Te(d)?(u[d]=null,g(d)&&(f[d]=null)):Ue(d)&&(d.value=null)),ie(c))Gs(c,a,12,[l,u]);else{const x=Te(c),L=Ue(c);if(x||L){const J=()=>{if(e.f){const j=x?g(c)?f[c]:u[c]:c.value;o?ee(j)&&mo(j,r):ee(j)?j.includes(r)||j.push(r):x?(u[c]=[r],g(c)&&(f[c]=u[c])):(c.value=[r],e.k&&(u[e.k]=c.value))}else x?(u[c]=l,g(c)&&(f[c]=l)):L&&(c.value=l,e.k&&(u[e.k]=l))};l?(J.id=-1,Ve(J,s)):J()}}}kn().requestIdleCallback;kn().cancelIdleCallback;const Es=e=>!!e.type.__asyncLoader,Sn=e=>e.type.__isKeepAlive;function wa(e,t){Li(e,"a",t)}function ka(e,t){Li(e,"da",t)}function Li(e,t,s=Ne){const n=e.__wdc||(e.__wdc=()=>{let o=s;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Tn(t,n,s),s){let o=s.parent;for(;o&&o.parent;)Sn(o.parent.vnode)&&xa(n,t,s,o),o=o.parent}}function xa(e,t,s,n){const o=Tn(t,e,n,!0);En(()=>{mo(n[t],o)},s)}function Tn(e,t,s=Ne,n=!1){if(s){const o=s[e]||(s[e]=[]),r=t.__weh||(t.__weh=(...l)=>{St();const a=Js(s),c=it(t,s,e,l);return a(),Tt(),c});return n?o.unshift(r):o.push(r),r}}const Et=e=>(t,s=Ne)=>{(!Vs||e==="sp")&&Tn(e,(...n)=>t(...n),s)},Ca=Et("bm"),Dt=Et("m"),Ii=Et("bu"),$a=Et("u"),Ni=Et("bum"),En=Et("um"),Sa=Et("sp"),Ta=Et("rtg"),Ea=Et("rtc");function Aa(e,t=Ne){Tn("ec",e,t)}const Ma="components",ji=Symbol.for("v-ndc");function Oa(e){return Te(e)?Pa(Ma,e,!1)||e:e||ji}function Pa(e,t,s=!0,n=!1){const o=Qe||Ne;if(o){const r=o.type;{const a=yc(r,!1);if(a&&(a===t||a===nt(t)||a===wn(nt(t))))return r}const l=Jo(o[e]||r[e],t)||Jo(o.appContext[e],t);return!l&&n?r:l}}function Jo(e,t){return e&&(e[t]||e[nt(t)]||e[wn(nt(t))])}function Le(e,t,s,n){let o;const r=s,l=ee(e);if(l||Te(e)){const a=l&&rs(e);let c=!1,d=!1;a&&(c=!tt(e),d=jt(e),e=xn(e)),o=new Array(e.length);for(let u=0,f=e.length;ut(a,c,void 0,r));else{const a=Object.keys(e);o=new Array(a.length);for(let c=0,d=a.length;ce?nl(e)?On(e):so(e.parent):null,As=Re(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>so(e.parent),$root:e=>so(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ui(e),$forceUpdate:e=>e.f||(e.f=()=>{To(e.update)}),$nextTick:e=>e.n||(e.n=$n.bind(e.proxy)),$watch:e=>Xa.bind(e)}),Un=(e,t)=>e!==we&&!e.__isScriptSetup&&he(e,t),Ra={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:o,props:r,accessCache:l,type:a,appContext:c}=e;let d;if(t[0]!=="$"){const g=l[t];if(g!==void 0)switch(g){case 1:return n[t];case 2:return o[t];case 4:return s[t];case 3:return r[t]}else{if(Un(n,t))return l[t]=1,n[t];if(o!==we&&he(o,t))return l[t]=2,o[t];if((d=e.propsOptions[0])&&he(d,t))return l[t]=3,r[t];if(s!==we&&he(s,t))return l[t]=4,s[t];no&&(l[t]=0)}}const u=As[t];let f,v;if(u)return t==="$attrs"&&je(e.attrs,"get",""),u(e);if((f=a.__cssModules)&&(f=f[t]))return f;if(s!==we&&he(s,t))return l[t]=4,s[t];if(v=c.config.globalProperties,he(v,t))return v[t]},set({_:e},t,s){const{data:n,setupState:o,ctx:r}=e;return Un(o,t)?(o[t]=s,!0):n!==we&&he(n,t)?(n[t]=s,!0):he(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:o,propsOptions:r}},l){let a;return!!s[l]||e!==we&&he(e,l)||Un(t,l)||(a=r[0])&&he(a,l)||he(n,l)||he(As,l)||he(o.config.globalProperties,l)},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:he(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function Wo(e){return ee(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let no=!0;function La(e){const t=Ui(e),s=e.proxy,n=e.ctx;no=!1,t.beforeCreate&&Qo(t.beforeCreate,e,"bc");const{data:o,computed:r,methods:l,watch:a,provide:c,inject:d,created:u,beforeMount:f,mounted:v,beforeUpdate:g,updated:x,activated:L,deactivated:J,beforeDestroy:j,beforeUnmount:V,destroyed:T,unmounted:y,render:P,renderTracked:I,renderTriggered:C,errorCaptured:$,serverPrefetch:O,expose:W,inheritAttrs:te,components:k,directives:_,filters:B}=t;if(d&&Ia(d,n,null),l)for(const ae in l){const ce=l[ae];ie(ce)&&(n[ae]=ce.bind(s))}if(o){const ae=o.call(s,s);ke(ae)&&(e.data=hs(ae))}if(no=!0,r)for(const ae in r){const ce=r[ae],Ae=ie(ce)?ce.bind(s,s):ie(ce.get)?ce.get.bind(s,s):ot,G=!ie(ce)&&ie(ce.set)?ce.set.bind(s):ot,b=ve({get:Ae,set:G});Object.defineProperty(n,ae,{enumerable:!0,configurable:!0,get:()=>b.value,set:ue=>b.value=ue})}if(a)for(const ae in a)Bi(a[ae],n,s,ae);if(c){const ae=ie(c)?c.call(s):c;Reflect.ownKeys(ae).forEach(ce=>{on(ce,ae[ce])})}u&&Qo(u,e,"c");function oe(ae,ce){ee(ce)?ce.forEach(Ae=>ae(Ae.bind(s))):ce&&ae(ce.bind(s))}if(oe(Ca,f),oe(Dt,v),oe(Ii,g),oe($a,x),oe(wa,L),oe(ka,J),oe(Aa,$),oe(Ea,I),oe(Ta,C),oe(Ni,V),oe(En,y),oe(Sa,O),ee(W))if(W.length){const ae=e.exposed||(e.exposed={});W.forEach(ce=>{Object.defineProperty(ae,ce,{get:()=>s[ce],set:Ae=>s[ce]=Ae})})}else e.exposed||(e.exposed={});P&&e.render===ot&&(e.render=P),te!=null&&(e.inheritAttrs=te),k&&(e.components=k),_&&(e.directives=_),O&&Ri(e)}function Ia(e,t,s=ot){ee(e)&&(e=oo(e));for(const n in e){const o=e[n];let r;ke(o)?"default"in o?r=$t(o.from||n,o.default,!0):r=$t(o.from||n):r=$t(o),Ue(r)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>r.value,set:l=>r.value=l}):t[n]=r}}function Qo(e,t,s){it(ee(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function Bi(e,t,s,n){let o=n.includes(".")?Yi(s,n):()=>s[n];if(Te(e)){const r=t[e];ie(r)&&as(o,r)}else if(ie(e))as(o,e.bind(s));else if(ke(e))if(ee(e))e.forEach(r=>Bi(r,t,s,n));else{const r=ie(e.handler)?e.handler.bind(s):t[e.handler];ie(r)&&as(o,r,e)}}function Ui(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:o,optionsCache:r,config:{optionMergeStrategies:l}}=e.appContext,a=r.get(t);let c;return a?c=a:!o.length&&!s&&!n?c=t:(c={},o.length&&o.forEach(d=>hn(c,d,l,!0)),hn(c,t,l)),ke(t)&&r.set(t,c),c}function hn(e,t,s,n=!1){const{mixins:o,extends:r}=t;r&&hn(e,r,s,!0),o&&o.forEach(l=>hn(e,l,s,!0));for(const l in t)if(!(n&&l==="expose")){const a=Na[l]||s&&s[l];e[l]=a?a(e[l],t[l]):t[l]}return e}const Na={data:Yo,props:Zo,emits:Zo,methods:ws,computed:ws,beforeCreate:De,created:De,beforeMount:De,mounted:De,beforeUpdate:De,updated:De,beforeDestroy:De,beforeUnmount:De,destroyed:De,unmounted:De,activated:De,deactivated:De,errorCaptured:De,serverPrefetch:De,components:ws,directives:ws,watch:Ba,provide:Yo,inject:ja};function Yo(e,t){return t?e?function(){return Re(ie(e)?e.call(this,this):e,ie(t)?t.call(this,this):t)}:t:e}function ja(e,t){return ws(oo(e),oo(t))}function oo(e){if(ee(e)){const t={};for(let s=0;s1)return s&&ie(t)?t.call(n&&n.proxy):t}}const Di={},Vi=()=>Object.create(Di),Fi=e=>Object.getPrototypeOf(e)===Di;function Da(e,t,s,n=!1){const o={},r=Vi();e.propsDefaults=Object.create(null),qi(e,t,o,r);for(const l in e.propsOptions[0])l in o||(o[l]=void 0);s?e.props=n?o:fi(o):e.type.props?e.props=o:e.props=r,e.attrs=r}function Va(e,t,s,n){const{props:o,attrs:r,vnode:{patchFlag:l}}=e,a=fe(o),[c]=e.propsOptions;let d=!1;if((n||l>0)&&!(l&16)){if(l&8){const u=e.vnode.dynamicProps;for(let f=0;f{c=!0;const[v,g]=Ki(f,t,!0);Re(l,v),g&&a.push(...g)};!s&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!r&&!c)return ke(e)&&n.set(e,ns),ns;if(ee(r))for(let u=0;ue[0]==="_"||e==="$stable",Ao=e=>ee(e)?e.map(ht):[ht(e)],qa=(e,t,s)=>{if(t._n)return t;const n=xi((...o)=>Ao(t(...o)),s);return n._c=!1,n},zi=(e,t,s)=>{const n=e._ctx;for(const o in e){if(Eo(o))continue;const r=e[o];if(ie(r))t[o]=qa(o,r,n);else if(r!=null){const l=Ao(r);t[o]=()=>l}}},Gi=(e,t)=>{const s=Ao(t);e.slots.default=()=>s},Ji=(e,t,s)=>{for(const n in t)(s||!Eo(n))&&(e[n]=t[n])},Ka=(e,t,s)=>{const n=e.slots=Vi();if(e.vnode.shapeFlag&32){const o=t.__;o&&Wn(n,"__",o,!0);const r=t._;r?(Ji(n,t,s),s&&Wn(n,"_",r,!0)):zi(t,n)}else t&&Gi(e,t)},za=(e,t,s)=>{const{vnode:n,slots:o}=e;let r=!0,l=we;if(n.shapeFlag&32){const a=t._;a?s&&a===1?r=!1:Ji(o,t,s):(r=!t.$stable,zi(t,o)),l=t}else t&&(Gi(e,t),l={default:1});if(r)for(const a in o)!Eo(a)&&l[a]==null&&delete o[a]},Ve=ic;function Ga(e){return Ja(e)}function Ja(e,t){const s=kn();s.__VUE__=!0;const{insert:n,remove:o,patchProp:r,createElement:l,createText:a,createComment:c,setText:d,setElementText:u,parentNode:f,nextSibling:v,setScopeId:g=ot,insertStaticContent:x}=e,L=(p,h,m,A=null,R=null,M=null,F=void 0,D=null,H=!!h.dynamicChildren)=>{if(p===h)return;p&&!Gt(p,h)&&(A=S(p),ue(p,R,M,!0),p=null),h.patchFlag===-2&&(H=!1,h.dynamicChildren=null);const{type:N,ref:se,shapeFlag:K}=h;switch(N){case Mn:J(p,h,m,A);break;case Ke:j(p,h,m,A);break;case Ms:p==null&&V(h,m,A,F);break;case ye:k(p,h,m,A,R,M,F,D,H);break;default:K&1?P(p,h,m,A,R,M,F,D,H):K&6?_(p,h,m,A,R,M,F,D,H):(K&64||K&128)&&N.process(p,h,m,A,R,M,F,D,H,Q)}se!=null&&R?Ts(se,p&&p.ref,M,h||p,!h):se==null&&p&&p.ref!=null&&Ts(p.ref,null,M,p,!0)},J=(p,h,m,A)=>{if(p==null)n(h.el=a(h.children),m,A);else{const R=h.el=p.el;h.children!==p.children&&d(R,h.children)}},j=(p,h,m,A)=>{p==null?n(h.el=c(h.children||""),m,A):h.el=p.el},V=(p,h,m,A)=>{[p.el,p.anchor]=x(p.children,h,m,A,p.el,p.anchor)},T=({el:p,anchor:h},m,A)=>{let R;for(;p&&p!==h;)R=v(p),n(p,m,A),p=R;n(h,m,A)},y=({el:p,anchor:h})=>{let m;for(;p&&p!==h;)m=v(p),o(p),p=m;o(h)},P=(p,h,m,A,R,M,F,D,H)=>{h.type==="svg"?F="svg":h.type==="math"&&(F="mathml"),p==null?I(h,m,A,R,M,F,D,H):O(p,h,R,M,F,D,H)},I=(p,h,m,A,R,M,F,D)=>{let H,N;const{props:se,shapeFlag:K,transition:X,dirs:re}=p;if(H=p.el=l(p.type,M,se&&se.is,se),K&8?u(H,p.children):K&16&&$(p.children,H,null,A,R,Hn(p,M),F,D),re&&Vt(p,null,A,"created"),C(H,p,p.scopeId,F,A),se){for(const xe in se)xe!=="value"&&!xs(xe)&&r(H,xe,null,se[xe],M,A);"value"in se&&r(H,"value",null,se.value,M),(N=se.onVnodeBeforeMount)&&ft(N,A,p)}re&&Vt(p,null,A,"beforeMount");const de=Wa(R,X);de&&X.beforeEnter(H),n(H,h,m),((N=se&&se.onVnodeMounted)||de||re)&&Ve(()=>{N&&ft(N,A,p),de&&X.enter(H),re&&Vt(p,null,A,"mounted")},R)},C=(p,h,m,A,R)=>{if(m&&g(p,m),A)for(let M=0;M{for(let N=H;N{const D=h.el=p.el;let{patchFlag:H,dynamicChildren:N,dirs:se}=h;H|=p.patchFlag&16;const K=p.props||we,X=h.props||we;let re;if(m&&Ft(m,!1),(re=X.onVnodeBeforeUpdate)&&ft(re,m,h,p),se&&Vt(h,p,m,"beforeUpdate"),m&&Ft(m,!0),(K.innerHTML&&X.innerHTML==null||K.textContent&&X.textContent==null)&&u(D,""),N?W(p.dynamicChildren,N,D,m,A,Hn(h,R),M):F||ce(p,h,D,null,m,A,Hn(h,R),M,!1),H>0){if(H&16)te(D,K,X,m,R);else if(H&2&&K.class!==X.class&&r(D,"class",null,X.class,R),H&4&&r(D,"style",K.style,X.style,R),H&8){const de=h.dynamicProps;for(let xe=0;xe{re&&ft(re,m,h,p),se&&Vt(h,p,m,"updated")},A)},W=(p,h,m,A,R,M,F)=>{for(let D=0;D{if(h!==m){if(h!==we)for(const M in h)!xs(M)&&!(M in m)&&r(p,M,h[M],null,R,A);for(const M in m){if(xs(M))continue;const F=m[M],D=h[M];F!==D&&M!=="value"&&r(p,M,D,F,R,A)}"value"in m&&r(p,"value",h.value,m.value,R)}},k=(p,h,m,A,R,M,F,D,H)=>{const N=h.el=p?p.el:a(""),se=h.anchor=p?p.anchor:a("");let{patchFlag:K,dynamicChildren:X,slotScopeIds:re}=h;re&&(D=D?D.concat(re):re),p==null?(n(N,m,A),n(se,m,A),$(h.children||[],m,se,R,M,F,D,H)):K>0&&K&64&&X&&p.dynamicChildren?(W(p.dynamicChildren,X,m,R,M,F,D),(h.key!=null||R&&h===R.subTree)&&Mo(p,h,!0)):ce(p,h,m,se,R,M,F,D,H)},_=(p,h,m,A,R,M,F,D,H)=>{h.slotScopeIds=D,p==null?h.shapeFlag&512?R.ctx.activate(h,m,A,F,H):B(h,m,A,R,M,F,H):ne(p,h,H)},B=(p,h,m,A,R,M,F)=>{const D=p.component=pc(p,A,R);if(Sn(p)&&(D.ctx.renderer=Q),hc(D,!1,F),D.asyncDep){if(R&&R.registerDep(D,oe,F),!p.el){const H=D.subTree=Be(Ke);j(null,H,h,m)}}else oe(D,p,h,m,R,M,F)},ne=(p,h,m)=>{const A=h.component=p.component;if(oc(p,h,m))if(A.asyncDep&&!A.asyncResolved){ae(A,h,m);return}else A.next=h,A.update();else h.el=p.el,A.vnode=h},oe=(p,h,m,A,R,M,F)=>{const D=()=>{if(p.isMounted){let{next:K,bu:X,u:re,parent:de,vnode:xe}=p;{const ut=Wi(p);if(ut){K&&(K.el=xe.el,ae(p,K,F)),ut.asyncDep.then(()=>{p.isUnmounted||D()});return}}let ge=K,ze;Ft(p,!1),K?(K.el=xe.el,ae(p,K,F)):K=xe,X&&sn(X),(ze=K.props&&K.props.onVnodeBeforeUpdate)&&ft(ze,de,K,xe),Ft(p,!0);const Ge=tr(p),ct=p.subTree;p.subTree=Ge,L(ct,Ge,f(ct.el),S(ct),p,R,M),K.el=Ge.el,ge===null&&rc(p,Ge.el),re&&Ve(re,R),(ze=K.props&&K.props.onVnodeUpdated)&&Ve(()=>ft(ze,de,K,xe),R)}else{let K;const{el:X,props:re}=h,{bm:de,m:xe,parent:ge,root:ze,type:Ge}=p,ct=Es(h);Ft(p,!1),de&&sn(de),!ct&&(K=re&&re.onVnodeBeforeMount)&&ft(K,ge,h),Ft(p,!0);{ze.ce&&ze.ce._def.shadowRoot!==!1&&ze.ce._injectChildStyle(Ge);const ut=p.subTree=tr(p);L(null,ut,m,A,p,R,M),h.el=ut.el}if(xe&&Ve(xe,R),!ct&&(K=re&&re.onVnodeMounted)){const ut=h;Ve(()=>ft(K,ge,ut),R)}(h.shapeFlag&256||ge&&Es(ge.vnode)&&ge.vnode.shapeFlag&256)&&p.a&&Ve(p.a,R),p.isMounted=!0,h=m=A=null}};p.scope.on();const H=p.effect=new Zr(D);p.scope.off();const N=p.update=H.run.bind(H),se=p.job=H.runIfDirty.bind(H);se.i=p,se.id=p.uid,H.scheduler=()=>To(se),Ft(p,!0),N()},ae=(p,h,m)=>{h.component=p;const A=p.vnode.props;p.vnode=h,p.next=null,Va(p,h.props,A,m),za(p,h.children,m),St(),Fo(p),Tt()},ce=(p,h,m,A,R,M,F,D,H=!1)=>{const N=p&&p.children,se=p?p.shapeFlag:0,K=h.children,{patchFlag:X,shapeFlag:re}=h;if(X>0){if(X&128){G(N,K,m,A,R,M,F,D,H);return}else if(X&256){Ae(N,K,m,A,R,M,F,D,H);return}}re&8?(se&16&&He(N,R,M),K!==N&&u(m,K)):se&16?re&16?G(N,K,m,A,R,M,F,D,H):He(N,R,M,!0):(se&8&&u(m,""),re&16&&$(K,m,A,R,M,F,D,H))},Ae=(p,h,m,A,R,M,F,D,H)=>{p=p||ns,h=h||ns;const N=p.length,se=h.length,K=Math.min(N,se);let X;for(X=0;Xse?He(p,R,M,!0,!1,K):$(h,m,A,R,M,F,D,H,K)},G=(p,h,m,A,R,M,F,D,H)=>{let N=0;const se=h.length;let K=p.length-1,X=se-1;for(;N<=K&&N<=X;){const re=p[N],de=h[N]=H?Lt(h[N]):ht(h[N]);if(Gt(re,de))L(re,de,m,null,R,M,F,D,H);else break;N++}for(;N<=K&&N<=X;){const re=p[K],de=h[X]=H?Lt(h[X]):ht(h[X]);if(Gt(re,de))L(re,de,m,null,R,M,F,D,H);else break;K--,X--}if(N>K){if(N<=X){const re=X+1,de=reX)for(;N<=K;)ue(p[N],R,M,!0),N++;else{const re=N,de=N,xe=new Map;for(N=de;N<=X;N++){const Ye=h[N]=H?Lt(h[N]):ht(h[N]);Ye.key!=null&&xe.set(Ye.key,N)}let ge,ze=0;const Ge=X-de+1;let ct=!1,ut=0;const vs=new Array(Ge);for(N=0;N=Ge){ue(Ye,R,M,!0);continue}let dt;if(Ye.key!=null)dt=xe.get(Ye.key);else for(ge=de;ge<=X;ge++)if(vs[ge-de]===0&&Gt(Ye,h[ge])){dt=ge;break}dt===void 0?ue(Ye,R,M,!0):(vs[dt-de]=N+1,dt>=ut?ut=dt:ct=!0,L(Ye,h[dt],m,null,R,M,F,D,H),ze++)}const jo=ct?Qa(vs):ns;for(ge=jo.length-1,N=Ge-1;N>=0;N--){const Ye=de+N,dt=h[Ye],Bo=Ye+1{const{el:M,type:F,transition:D,children:H,shapeFlag:N}=p;if(N&6){b(p.component.subTree,h,m,A);return}if(N&128){p.suspense.move(h,m,A);return}if(N&64){F.move(p,h,m,Q);return}if(F===ye){n(M,h,m);for(let K=0;KD.enter(M),R);else{const{leave:K,delayLeave:X,afterLeave:re}=D,de=()=>{p.ctx.isUnmounted?o(M):n(M,h,m)},xe=()=>{K(M,()=>{de(),re&&re()})};X?X(M,de,xe):xe()}else n(M,h,m)},ue=(p,h,m,A=!1,R=!1)=>{const{type:M,props:F,ref:D,children:H,dynamicChildren:N,shapeFlag:se,patchFlag:K,dirs:X,cacheIndex:re}=p;if(K===-2&&(R=!1),D!=null&&(St(),Ts(D,null,m,p,!0),Tt()),re!=null&&(h.renderCache[re]=void 0),se&256){h.ctx.deactivate(p);return}const de=se&1&&X,xe=!Es(p);let ge;if(xe&&(ge=F&&F.onVnodeBeforeUnmount)&&ft(ge,h,p),se&6)Se(p.component,m,A);else{if(se&128){p.suspense.unmount(m,A);return}de&&Vt(p,null,h,"beforeUnmount"),se&64?p.type.remove(p,h,m,Q,A):N&&!N.hasOnce&&(M!==ye||K>0&&K&64)?He(N,h,m,!1,!0):(M===ye&&K&384||!R&&se&16)&&He(H,h,m),A&&Y(p)}(xe&&(ge=F&&F.onVnodeUnmounted)||de)&&Ve(()=>{ge&&ft(ge,h,p),de&&Vt(p,null,h,"unmounted")},m)},Y=p=>{const{type:h,el:m,anchor:A,transition:R}=p;if(h===ye){me(m,A);return}if(h===Ms){y(p);return}const M=()=>{o(m),R&&!R.persisted&&R.afterLeave&&R.afterLeave()};if(p.shapeFlag&1&&R&&!R.persisted){const{leave:F,delayLeave:D}=R,H=()=>F(m,M);D?D(p.el,M,H):H()}else M()},me=(p,h)=>{let m;for(;p!==h;)m=v(p),o(p),p=m;o(h)},Se=(p,h,m)=>{const{bum:A,scope:R,job:M,subTree:F,um:D,m:H,a:N,parent:se,slots:{__:K}}=p;er(H),er(N),A&&sn(A),se&&ee(K)&&K.forEach(X=>{se.renderCache[X]=void 0}),R.stop(),M&&(M.flags|=8,ue(F,p,h,m)),D&&Ve(D,h),Ve(()=>{p.isUnmounted=!0},h),h&&h.pendingBranch&&!h.isUnmounted&&p.asyncDep&&!p.asyncResolved&&p.suspenseId===h.pendingId&&(h.deps--,h.deps===0&&h.resolve())},He=(p,h,m,A=!1,R=!1,M=0)=>{for(let F=M;F{if(p.shapeFlag&6)return S(p.component.subTree);if(p.shapeFlag&128)return p.suspense.next();const h=v(p.anchor||p.el),m=h&&h[Ci];return m?v(m):h};let z=!1;const q=(p,h,m)=>{p==null?h._vnode&&ue(h._vnode,null,null,!0):L(h._vnode||null,p,h,null,null,null,m),h._vnode=p,z||(z=!0,Fo(),_i(),z=!1)},Q={p:L,um:ue,m:b,r:Y,mt:B,mc:$,pc:ce,pbc:W,n:S,o:e};return{render:q,hydrate:void 0,createApp:Ha(q)}}function Hn({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function Ft({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Wa(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Mo(e,t,s=!1){const n=e.children,o=t.children;if(ee(n)&&ee(o))for(let r=0;r>1,e[s[a]]0&&(t[n]=s[r-1]),s[r]=n)}}for(r=s.length,l=s[r-1];r-- >0;)s[r]=l,l=t[l];return s}function Wi(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Wi(t)}function er(e){if(e)for(let t=0;t$t(Ya);function as(e,t,s){return Qi(e,t,s)}function Qi(e,t,s=we){const{immediate:n,deep:o,flush:r,once:l}=s,a=Re({},s),c=t&&n||!t&&r!=="post";let d;if(Vs){if(r==="sync"){const g=Za();d=g.__watcherHandles||(g.__watcherHandles=[])}else if(!c){const g=()=>{};return g.stop=ot,g.resume=ot,g.pause=ot,g}}const u=Ne;a.call=(g,x,L)=>it(g,u,x,L);let f=!1;r==="post"?a.scheduler=g=>{Ve(g,u&&u.suspense)}:r!=="sync"&&(f=!0,a.scheduler=(g,x)=>{x?g():To(g)}),a.augmentJob=g=>{t&&(g.flags|=4),f&&(g.flags|=2,u&&(g.id=u.uid,g.i=u))};const v=pa(e,t,a);return Vs&&(d?d.push(v):c&&v()),v}function Xa(e,t,s){const n=this.proxy,o=Te(e)?e.includes(".")?Yi(n,e):()=>n[e]:e.bind(n,n);let r;ie(t)?r=t:(r=t.handler,s=t);const l=Js(this),a=Qi(o,r.bind(n),s);return l(),a}function Yi(e,t){const s=t.split(".");return()=>{let n=e;for(let o=0;ot==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${nt(t)}Modifiers`]||e[`${Ht(t)}Modifiers`];function tc(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||we;let o=s;const r=t.startsWith("update:"),l=r&&ec(n,t.slice(7));l&&(l.trim&&(o=s.map(u=>Te(u)?u.trim():u)),l.number&&(o=s.map(cn)));let a,c=n[a=Rn(t)]||n[a=Rn(nt(t))];!c&&r&&(c=n[a=Rn(Ht(t))]),c&&it(c,e,6,o);const d=n[a+"Once"];if(d){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,it(d,e,6,o)}}function Zi(e,t,s=!1){const n=t.emitsCache,o=n.get(e);if(o!==void 0)return o;const r=e.emits;let l={},a=!1;if(!ie(e)){const c=d=>{const u=Zi(d,t,!0);u&&(a=!0,Re(l,u))};!s&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!r&&!a?(ke(e)&&n.set(e,null),null):(ee(r)?r.forEach(c=>l[c]=null):Re(l,r),ke(e)&&n.set(e,l),l)}function An(e,t){return!e||!bn(t)?!1:(t=t.slice(2).replace(/Once$/,""),he(e,t[0].toLowerCase()+t.slice(1))||he(e,Ht(t))||he(e,t))}function tr(e){const{type:t,vnode:s,proxy:n,withProxy:o,propsOptions:[r],slots:l,attrs:a,emit:c,render:d,renderCache:u,props:f,data:v,setupState:g,ctx:x,inheritAttrs:L}=e,J=pn(e);let j,V;try{if(s.shapeFlag&4){const y=o||n,P=y;j=ht(d.call(P,y,u,f,g,v,x)),V=a}else{const y=t;j=ht(y.length>1?y(f,{attrs:a,slots:l,emit:c}):y(f,null)),V=t.props?a:sc(a)}}catch(y){Os.length=0,Cn(y,e,1),j=Be(Ke)}let T=j;if(V&&L!==!1){const y=Object.keys(V),{shapeFlag:P}=T;y.length&&P&7&&(r&&y.some(go)&&(V=nc(V,r)),T=Bt(T,V,!1,!0))}return s.dirs&&(T=Bt(T,null,!1,!0),T.dirs=T.dirs?T.dirs.concat(s.dirs):s.dirs),s.transition&&Hs(T,s.transition),j=T,pn(J),j}const sc=e=>{let t;for(const s in e)(s==="class"||s==="style"||bn(s))&&((t||(t={}))[s]=e[s]);return t},nc=(e,t)=>{const s={};for(const n in e)(!go(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function oc(e,t,s){const{props:n,children:o,component:r}=e,{props:l,children:a,patchFlag:c}=t,d=r.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&c>=0){if(c&1024)return!0;if(c&16)return n?sr(n,l,d):!!l;if(c&8){const u=t.dynamicProps;for(let f=0;fe.__isSuspense;function ic(e,t){t&&t.pendingBranch?ee(e)?t.effects.push(...e):t.effects.push(e):bi(e)}const ye=Symbol.for("v-fgt"),Mn=Symbol.for("v-txt"),Ke=Symbol.for("v-cmt"),Ms=Symbol.for("v-stc"),Os=[];let Xe=null;function w(e=!1){Os.push(Xe=e?null:[])}function lc(){Os.pop(),Xe=Os[Os.length-1]||null}let Ds=1;function nr(e,t=!1){Ds+=e,e<0&&Xe&&t&&(Xe.hasOnce=!0)}function el(e){return e.dynamicChildren=Ds>0?Xe||ns:null,lc(),Ds>0&&Xe&&Xe.push(e),e}function E(e,t,s,n,o,r){return el(i(e,t,s,n,o,r,!0))}function Ze(e,t,s,n,o){return el(Be(e,t,s,n,o,!0))}function vn(e){return e?e.__v_isVNode===!0:!1}function Gt(e,t){return e.type===t.type&&e.key===t.key}const tl=({key:e})=>e??null,rn=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?Te(e)||Ue(e)||ie(e)?{i:Qe,r:e,k:t,f:!!s}:e:null);function i(e,t=null,s=null,n=0,o=null,r=e===ye?0:1,l=!1,a=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&tl(t),ref:t&&rn(t),scopeId:ki,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:n,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:Qe};return a?(Po(c,s),r&128&&e.normalize(c)):s&&(c.shapeFlag|=Te(s)?8:16),Ds>0&&!l&&Xe&&(c.patchFlag>0||r&6)&&c.patchFlag!==32&&Xe.push(c),c}const Be=ac;function ac(e,t=null,s=null,n=0,o=null,r=!1){if((!e||e===ji)&&(e=Ke),vn(e)){const a=Bt(e,t,!0);return s&&Po(a,s),Ds>0&&!r&&Xe&&(a.shapeFlag&6?Xe[Xe.indexOf(e)]=a:Xe.push(a)),a.patchFlag=-2,a}if(bc(e)&&(e=e.__vccOpts),t){t=cc(t);let{class:a,style:c}=t;a&&!Te(a)&&(t.class=be(a)),ke(c)&&(So(c)&&!ee(c)&&(c=Re({},c)),t.style=Ns(c))}const l=Te(e)?1:Xi(e)?128:$i(e)?64:ke(e)?4:ie(e)?2:0;return i(e,t,s,n,o,l,r,!0)}function cc(e){return e?So(e)||Fi(e)?Re({},e):e:null}function Bt(e,t,s=!1,n=!1){const{props:o,ref:r,patchFlag:l,children:a,transition:c}=e,d=t?uc(o||{},t):o,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:d,key:d&&tl(d),ref:t&&t.ref?s&&r?ee(r)?r.concat(rn(t)):[r,rn(t)]:rn(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ye?l===-1?16:l|16:l,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Bt(e.ssContent),ssFallback:e.ssFallback&&Bt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&n&&Hs(u,c.clone(u)),u}function Pe(e=" ",t=0){return Be(Mn,null,e,t)}function Oo(e,t){const s=Be(Ms,null,e);return s.staticCount=t,s}function le(e="",t=!1){return t?(w(),Ze(Ke,null,e)):Be(Ke,null,e)}function ht(e){return e==null||typeof e=="boolean"?Be(Ke):ee(e)?Be(ye,null,e.slice()):vn(e)?Lt(e):Be(Mn,null,String(e))}function Lt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Bt(e)}function Po(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(ee(t))s=16;else if(typeof t=="object")if(n&65){const o=t.default;o&&(o._c&&(o._d=!1),Po(e,o()),o._c&&(o._d=!0));return}else{s=32;const o=t._;!o&&!Fi(t)?t._ctx=Qe:o===3&&Qe&&(Qe.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ie(t)?(t={default:t,_ctx:Qe},s=32):(t=String(t),n&64?(s=16,t=[Pe(t)]):s=8);e.children=t,e.shapeFlag|=s}function uc(...e){const t={};for(let s=0;sNe||Qe;let gn,io;{const e=kn(),t=(s,n)=>{let o;return(o=e[s])||(o=e[s]=[]),o.push(n),r=>{o.length>1?o.forEach(l=>l(r)):o[0](r)}};gn=t("__VUE_INSTANCE_SETTERS__",s=>Ne=s),io=t("__VUE_SSR_SETTERS__",s=>Vs=s)}const Js=e=>{const t=Ne;return gn(e),e.scope.on(),()=>{e.scope.off(),gn(t)}},or=()=>{Ne&&Ne.scope.off(),gn(null)};function nl(e){return e.vnode.shapeFlag&4}let Vs=!1;function hc(e,t=!1,s=!1){t&&io(t);const{props:n,children:o}=e.vnode,r=nl(e);Da(e,n,r,t),Ka(e,o,s||t);const l=r?vc(e,t):void 0;return t&&io(!1),l}function vc(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Ra);const{setup:n}=s;if(n){St();const o=e.setupContext=n.length>1?mc(e):null,r=Js(e),l=Gs(n,e,0,[e.props,o]),a=Kr(l);if(Tt(),r(),(a||e.sp)&&!Es(e)&&Ri(e),a){if(l.then(or,or),t)return l.then(c=>{rr(e,c)}).catch(c=>{Cn(c,e,0)});e.asyncDep=l}else rr(e,l)}else ol(e)}function rr(e,t,s){ie(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ke(t)&&(e.setupState=gi(t)),ol(e)}function ol(e,t,s){const n=e.type;e.render||(e.render=n.render||ot);{const o=Js(e);St();try{La(e)}finally{Tt(),o()}}}const gc={get(e,t){return je(e,"get",""),e[t]}};function mc(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,gc),slots:e.slots,emit:e.emit,expose:t}}function On(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(gi(hi(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in As)return As[s](e)},has(t,s){return s in t||s in As}})):e.proxy}function yc(e,t=!0){return ie(e)?e.displayName||e.name:e.name||t&&e.__name}function bc(e){return ie(e)&&"__vccOpts"in e}const ve=(e,t)=>da(e,t,Vs);function Ro(e,t,s){const n=arguments.length;return n===2?ke(t)&&!ee(t)?vn(t)?Be(e,null,[t]):Be(e,t):Be(e,null,t):(n>3?s=Array.prototype.slice.call(arguments,2):n===3&&vn(s)&&(s=[s]),Be(e,t,s))}const _c="3.5.17";/** +* @vue/runtime-dom v3.5.17 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let lo;const ir=typeof window<"u"&&window.trustedTypes;if(ir)try{lo=ir.createPolicy("vue",{createHTML:e=>e})}catch{}const rl=lo?e=>lo.createHTML(e):e=>e,wc="http://www.w3.org/2000/svg",kc="http://www.w3.org/1998/Math/MathML",wt=typeof document<"u"?document:null,lr=wt&&wt.createElement("template"),xc={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const o=t==="svg"?wt.createElementNS(wc,e):t==="mathml"?wt.createElementNS(kc,e):s?wt.createElement(e,{is:s}):wt.createElement(e);return e==="select"&&n&&n.multiple!=null&&o.setAttribute("multiple",n.multiple),o},createText:e=>wt.createTextNode(e),createComment:e=>wt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>wt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,o,r){const l=s?s.previousSibling:t.lastChild;if(o&&(o===r||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),s),!(o===r||!(o=o.nextSibling)););else{lr.innerHTML=rl(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const a=lr.content;if(n==="svg"||n==="mathml"){const c=a.firstChild;for(;c.firstChild;)a.appendChild(c.firstChild);a.removeChild(c)}t.insertBefore(a,s)}return[l?l.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},Mt="transition",ys="animation",Fs=Symbol("_vtc"),il={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Cc=Re({},Ei,il),$c=e=>(e.displayName="Transition",e.props=Cc,e),Sc=$c((e,{slots:t})=>Ro(_a,Tc(e),t)),qt=(e,t=[])=>{ee(e)?e.forEach(s=>s(...t)):e&&e(...t)},ar=e=>e?ee(e)?e.some(t=>t.length>1):e.length>1:!1;function Tc(e){const t={};for(const k in e)k in il||(t[k]=e[k]);if(e.css===!1)return t;const{name:s="v",type:n,duration:o,enterFromClass:r=`${s}-enter-from`,enterActiveClass:l=`${s}-enter-active`,enterToClass:a=`${s}-enter-to`,appearFromClass:c=r,appearActiveClass:d=l,appearToClass:u=a,leaveFromClass:f=`${s}-leave-from`,leaveActiveClass:v=`${s}-leave-active`,leaveToClass:g=`${s}-leave-to`}=e,x=Ec(o),L=x&&x[0],J=x&&x[1],{onBeforeEnter:j,onEnter:V,onEnterCancelled:T,onLeave:y,onLeaveCancelled:P,onBeforeAppear:I=j,onAppear:C=V,onAppearCancelled:$=T}=t,O=(k,_,B,ne)=>{k._enterCancelled=ne,Kt(k,_?u:a),Kt(k,_?d:l),B&&B()},W=(k,_)=>{k._isLeaving=!1,Kt(k,f),Kt(k,g),Kt(k,v),_&&_()},te=k=>(_,B)=>{const ne=k?C:V,oe=()=>O(_,k,B);qt(ne,[_,oe]),cr(()=>{Kt(_,k?c:r),yt(_,k?u:a),ar(ne)||ur(_,n,L,oe)})};return Re(t,{onBeforeEnter(k){qt(j,[k]),yt(k,r),yt(k,l)},onBeforeAppear(k){qt(I,[k]),yt(k,c),yt(k,d)},onEnter:te(!1),onAppear:te(!0),onLeave(k,_){k._isLeaving=!0;const B=()=>W(k,_);yt(k,f),k._enterCancelled?(yt(k,v),pr()):(pr(),yt(k,v)),cr(()=>{k._isLeaving&&(Kt(k,f),yt(k,g),ar(y)||ur(k,n,J,B))}),qt(y,[k,B])},onEnterCancelled(k){O(k,!1,void 0,!0),qt(T,[k])},onAppearCancelled(k){O(k,!0,void 0,!0),qt($,[k])},onLeaveCancelled(k){W(k),qt(P,[k])}})}function Ec(e){if(e==null)return null;if(ke(e))return[Dn(e.enter),Dn(e.leave)];{const t=Dn(e);return[t,t]}}function Dn(e){return Rl(e)}function yt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.add(s)),(e[Fs]||(e[Fs]=new Set)).add(t)}function Kt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.remove(n));const s=e[Fs];s&&(s.delete(t),s.size||(e[Fs]=void 0))}function cr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Ac=0;function ur(e,t,s,n){const o=e._endId=++Ac,r=()=>{o===e._endId&&n()};if(s!=null)return setTimeout(r,s);const{type:l,timeout:a,propCount:c}=Mc(e,t);if(!l)return n();const d=l+"end";let u=0;const f=()=>{e.removeEventListener(d,v),r()},v=g=>{g.target===e&&++u>=c&&f()};setTimeout(()=>{u(s[x]||"").split(", "),o=n(`${Mt}Delay`),r=n(`${Mt}Duration`),l=dr(o,r),a=n(`${ys}Delay`),c=n(`${ys}Duration`),d=dr(a,c);let u=null,f=0,v=0;t===Mt?l>0&&(u=Mt,f=l,v=r.length):t===ys?d>0&&(u=ys,f=d,v=c.length):(f=Math.max(l,d),u=f>0?l>d?Mt:ys:null,v=u?u===Mt?r.length:c.length:0);const g=u===Mt&&/\b(transform|all)(,|$)/.test(n(`${Mt}Property`).toString());return{type:u,timeout:f,propCount:v,hasTransform:g}}function dr(e,t){for(;e.lengthfr(s)+fr(e[n])))}function fr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function pr(){return document.body.offsetHeight}function Oc(e,t,s){const n=e[Fs];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const hr=Symbol("_vod"),Pc=Symbol("_vsh"),ll=Symbol("");function Rc(e){const t=sl();if(!t)return;const s=t.ut=(o=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(r=>mn(r,o))},n=()=>{const o=e(t.proxy);t.ce?mn(t.ce,o):ao(t.subTree,o),s(o)};Ii(()=>{bi(n)}),Dt(()=>{as(n,ot,{flush:"post"});const o=new MutationObserver(n);o.observe(t.subTree.el.parentNode,{childList:!0}),En(()=>o.disconnect())})}function ao(e,t){if(e.shapeFlag&128){const s=e.suspense;e=s.activeBranch,s.pendingBranch&&!s.isHydrating&&s.effects.push(()=>{ao(s.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)mn(e.el,t);else if(e.type===ye)e.children.forEach(s=>ao(s,t));else if(e.type===Ms){let{el:s,anchor:n}=e;for(;s&&(mn(s,t),s!==n);)s=s.nextSibling}}function mn(e,t){if(e.nodeType===1){const s=e.style;let n="";for(const o in t)s.setProperty(`--${o}`,t[o]),n+=`--${o}: ${t[o]};`;s[ll]=n}}const Lc=/(^|;)\s*display\s*:/;function Ic(e,t,s){const n=e.style,o=Te(s);let r=!1;if(s&&!o){if(t)if(Te(t))for(const l of t.split(";")){const a=l.slice(0,l.indexOf(":")).trim();s[a]==null&&ln(n,a,"")}else for(const l in t)s[l]==null&&ln(n,l,"");for(const l in s)l==="display"&&(r=!0),ln(n,l,s[l])}else if(o){if(t!==s){const l=n[ll];l&&(s+=";"+l),n.cssText=s,r=Lc.test(s)}}else t&&e.removeAttribute("style");hr in e&&(e[hr]=r?n.display:"",e[Pc]&&(n.display="none"))}const vr=/\s*!important$/;function ln(e,t,s){if(ee(s))s.forEach(n=>ln(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=Nc(e,t);vr.test(s)?e.setProperty(Ht(n),s.replace(vr,""),"important"):e[n]=s}}const gr=["Webkit","Moz","ms"],Vn={};function Nc(e,t){const s=Vn[t];if(s)return s;let n=nt(t);if(n!=="filter"&&n in e)return Vn[t]=n;n=wn(n);for(let o=0;oFn||(Hc.then(()=>Fn=0),Fn=Date.now());function Vc(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;it(Fc(n,s.value),t,5,[n])};return s.value=e,s.attached=Dc(),s}function Fc(e,t){if(ee(t)){const s=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{s.call(e),e._stopped=!0},t.map(n=>o=>!o._stopped&&n&&n(o))}else return t}const kr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,qc=(e,t,s,n,o,r)=>{const l=o==="svg";t==="class"?Oc(e,n,l):t==="style"?Ic(e,s,n):bn(t)?go(t)||Bc(e,t,s,n,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Kc(e,t,n,l))?(br(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&yr(e,t,n,l,r,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!Te(n))?br(e,nt(t),n,r,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),yr(e,t,n,l))};function Kc(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&kr(t)&&ie(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return kr(t)&&Te(s)?!1:t in e}const Ut=e=>{const t=e.props["onUpdate:modelValue"]||!1;return ee(t)?s=>sn(t,s):t};function zc(e){e.target.composing=!0}function xr(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const st=Symbol("_assign"),qe={created(e,{modifiers:{lazy:t,trim:s,number:n}},o){e[st]=Ut(o);const r=n||o.props&&o.props.type==="number";Ct(e,t?"change":"input",l=>{if(l.target.composing)return;let a=e.value;s&&(a=a.trim()),r&&(a=cn(a)),e[st](a)}),s&&Ct(e,"change",()=>{e.value=e.value.trim()}),t||(Ct(e,"compositionstart",zc),Ct(e,"compositionend",xr),Ct(e,"change",xr))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:o,number:r}},l){if(e[st]=Ut(l),e.composing)return;const a=(r||e.type==="number")&&!/^0\d/.test(e.value)?cn(e.value):e.value,c=t??"";a!==c&&(document.activeElement===e&&e.type!=="range"&&(n&&t===s||o&&e.value.trim()===c)||(e.value=c))}},an={deep:!0,created(e,t,s){e[st]=Ut(s),Ct(e,"change",()=>{const n=e._modelValue,o=us(e),r=e.checked,l=e[st];if(ee(n)){const a=bo(n,o),c=a!==-1;if(r&&!c)l(n.concat(o));else if(!r&&c){const d=[...n];d.splice(a,1),l(d)}}else if(ps(n)){const a=new Set(n);r?a.add(o):a.delete(o),l(a)}else l(al(e,r))})},mounted:Cr,beforeUpdate(e,t,s){e[st]=Ut(s),Cr(e,t,s)}};function Cr(e,{value:t,oldValue:s},n){e._modelValue=t;let o;if(ee(t))o=bo(t,n.props.value)>-1;else if(ps(t))o=t.has(n.props.value);else{if(t===s)return;o=Yt(t,al(e,!0))}e.checked!==o&&(e.checked=o)}const Gc={created(e,{value:t},s){e.checked=Yt(t,s.props.value),e[st]=Ut(s),Ct(e,"change",()=>{e[st](us(e))})},beforeUpdate(e,{value:t,oldValue:s},n){e[st]=Ut(n),t!==s&&(e.checked=Yt(t,n.props.value))}},vt={deep:!0,created(e,{value:t,modifiers:{number:s}},n){const o=ps(t);Ct(e,"change",()=>{const r=Array.prototype.filter.call(e.options,l=>l.selected).map(l=>s?cn(us(l)):us(l));e[st](e.multiple?o?new Set(r):r:r[0]),e._assigning=!0,$n(()=>{e._assigning=!1})}),e[st]=Ut(n)},mounted(e,{value:t}){$r(e,t)},beforeUpdate(e,t,s){e[st]=Ut(s)},updated(e,{value:t}){e._assigning||$r(e,t)}};function $r(e,t){const s=e.multiple,n=ee(t);if(!(s&&!n&&!ps(t))){for(let o=0,r=e.options.length;oString(d)===String(a)):l.selected=bo(t,a)>-1}else l.selected=t.has(a);else if(Yt(us(l),t)){e.selectedIndex!==o&&(e.selectedIndex=o);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function us(e){return"_value"in e?e._value:e.value}function al(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const Jc={created(e,t,s){en(e,t,s,null,"created")},mounted(e,t,s){en(e,t,s,null,"mounted")},beforeUpdate(e,t,s,n){en(e,t,s,n,"beforeUpdate")},updated(e,t,s,n){en(e,t,s,n,"updated")}};function Wc(e,t){switch(e){case"SELECT":return vt;case"TEXTAREA":return qe;default:switch(t){case"checkbox":return an;case"radio":return Gc;default:return qe}}}function en(e,t,s,n,o){const l=Wc(e.tagName,s.props&&s.props.type)[o];l&&l(e,t,s,n)}const Qc=["ctrl","shift","alt","meta"],Yc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Qc.some(s=>e[`${s}Key`]&&!t.includes(s))},Ps=(e,t)=>{const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=(o,...r)=>{for(let l=0;l{const s=e._withKeys||(e._withKeys={}),n=t.join(".");return s[n]||(s[n]=o=>{if(!("key"in o))return;const r=Ht(o.key);if(t.some(l=>l===r||Zc[l]===r))return e(o)})},Xc=Re({patchProp:qc},xc);let Sr;function eu(){return Sr||(Sr=Ga(Xc))}const ul=(...e)=>{const t=eu().createApp(...e),{mount:s}=t;return t.mount=n=>{const o=su(n);if(!o)return;const r=t._component;!ie(r)&&!r.render&&!r.template&&(r.template=o.innerHTML),o.nodeType===1&&(o.textContent="");const l=s(o,!1,tu(o));return o instanceof Element&&(o.removeAttribute("v-cloak"),o.setAttribute("data-v-app","")),l},t};function tu(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function su(e){return Te(e)?document.querySelector(e):e}/*! + * pinia v3.0.3 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */const nu=Symbol();var Tr;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(Tr||(Tr={}));function ou(){const e=Dl(!0),t=e.run(()=>Z({}));let s=[],n=[];const o=hi({install(r){o._a=r,r.provide(nu,o),r.config.globalProperties.$pinia=o,n.forEach(l=>s.push(l)),n=[]},use(r){return this._a?s.push(r):n.push(r),this},_p:s,_a:null,_e:e,_s:new Map,state:t});return o}const ru={class:"toast-content"},iu={class:"toast-icon-wrapper"},lu={class:"toast-icon"},au={class:"toast-message"},cu={key:0,class:"toast-title"},uu={class:"toast-text"},du={key:0,class:"toast-progress"},fu=at({__name:"Toast",props:{type:{default:"info"},title:{},message:{},duration:{default:2e3},closable:{type:Boolean,default:!0},showProgress:{type:Boolean,default:!0},position:{default:"center"},offset:{default:0},id:{}},emits:["close"],setup(e,{expose:t,emit:s}){const n={template:` + + + + `},o={template:` + + + + `},r={template:` + + + + `},l={template:` + + + + `},a=e,c=s,d=Z(!1),u=Z(100),f=Z(!1);let v=null,g=0,x=0;const L=ve(()=>{const $={position:"fixed",zIndex:"9999",pointerEvents:"none"};switch(a.position){case"top":return{...$,top:`${20+a.offset}px`,left:"50%",transform:"translateX(-50%)"};case"center":return{...$,top:"50%",left:"50%",transform:`translate(-50%, calc(-50% + ${a.offset}px))`};case"bottom":return{...$,bottom:`${20+a.offset}px`,left:"50%",transform:"translateX(-50%)"};default:return $}}),J=ve(()=>{switch(a.type){case"success":return n;case"error":return o;case"warning":return r;case"info":return l;default:return l}}),j=()=>{d.value=!0,g=Date.now(),x=a.duration,a.duration>0&&V()},V=()=>{v&&clearTimeout(v),v=setTimeout(()=>{T()},x),g=Date.now()},T=()=>{d.value=!1,v&&(clearTimeout(v),v=null),c("close")},y=()=>{v&&!f.value&&(f.value=!0,clearTimeout(v),x=x-(Date.now()-g))},P=()=>{f.value&&a.duration>0&&(f.value=!1,V())},I=$=>{},C=$=>{};return Dt(()=>{j()}),En(()=>{v&&clearTimeout(v)}),t({show:j,close:T,pause:y,resume:P}),($,O)=>(w(),Ze(ma,{to:"body"},[Be(Sc,{name:"toast","enter-active-class":"toast-enter-active","leave-active-class":"toast-leave-active","enter-from-class":"toast-enter-from","leave-to-class":"toast-leave-to",onEnter:I,onLeave:C},{default:xi(()=>[d.value?(w(),E("div",{key:0,class:be(["toast-overlay",`toast-${$.type}`]),style:Ns(L.value),onMouseenter:y,onMouseleave:P},[i("div",{class:be(["toast-container",`toast-${$.type}`])},[i("div",ru,[i("div",iu,[i("div",lu,[(w(),Ze(Oa(J.value)))])]),i("div",au,[$.title?(w(),E("div",cu,U($.title),1)):le("",!0),i("div",uu,U($.message),1)]),$.closable?(w(),E("button",{key:0,onClick:T,class:"toast-close"},O[0]||(O[0]=[i("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"currentColor"},[i("path",{d:"M9 7.586L13.657 3l1.414 1.414L10.414 9l4.657 4.586-1.414 1.414L9 10.414 4.343 15 3 13.657 7.586 9 3 4.343 4.343 3 9 7.586z"})],-1)]))):le("",!0)]),$.showProgress&&$.duration>0?(w(),E("div",du,[i("div",{class:"toast-progress-bar",style:Ns({width:u.value+"%",animationDuration:$.duration+"ms",animationPlayState:f.value?"paused":"running"})},null,4)])):le("",!0)],2)],38)):le("",!0)]),_:1})]))}}),At=(e,t)=>{const s=e.__vccOpts||e;for(const[n,o]of t)s[n]=o;return s},pu=At(fu,[["__scopeId","data-v-4c886fb0"]]),bt={success:3e3,error:6e3,warning:4e3,info:3e3,short:2e3};class hu{constructor(){gs(this,"toasts",[]);gs(this,"toastCounter",0)}show(t){const s=`toast-${++this.toastCounter}`,n=document.createElement("div"),o=this.calculateOffset(t.position||"top"),r=ul(pu,{...t,id:s,offset:o,onClose:()=>{this.remove(r)}});return r.mount(n),this.toasts.push({app:r,container:n,id:s}),r}calculateOffset(t){return this.toasts.filter(n=>!0).length*80}remove(t){const s=this.toasts.findIndex(({app:n})=>n===t);if(s>-1){const{app:n,container:o}=this.toasts[s];this.toasts.splice(s,1),n.unmount(),o.parentNode&&o.parentNode.removeChild(o),this.updatePositions()}}updatePositions(){this.toasts.forEach((t,s)=>{})}success(t,s,n){return typeof t=="string"?this.show({type:"success",title:s||"成功",message:t,duration:bt.success,...n}):this.show({type:"success",title:t.title||"成功",duration:bt.success,...t})}error(t,s,n){return typeof t=="string"?this.show({type:"error",title:s||"错误",message:t,duration:bt.error,...n}):this.show({type:"error",title:t.title||"错误",duration:bt.error,...t})}warning(t,s,n){return typeof t=="string"?this.show({type:"warning",title:s||"警告",message:t,duration:bt.warning,...n}):this.show({type:"warning",title:t.title||"警告",duration:bt.warning,...t})}info(t,s,n){return typeof t=="string"?this.show({type:"info",title:s||"提示",message:t,duration:bt.info,...n}):this.show({type:"info",title:t.title||"提示",duration:bt.info,...t})}quick(t,s="info"){return this.show({type:s,message:t,duration:bt.short,showProgress:!1,closable:!1})}persistent(t,s,n="info"){return this.show({type:n,title:s,message:t,duration:0,closable:!0})}clear(){this.toasts.forEach(({app:t})=>{this.remove(t)})}}const We=new hu;let es=null;async function vu(){if(es)return es;try{const s=await(await fetch("/sf-chain/config/api-info")).json();return es={baseUrl:s.baseUrl||"",endpoints:s.endpoints||{AI_MODELS:"/sf-chain/models",AI_OPERATIONS:"/sf-chain/operations",AI_CALL_LOGS:"/sf-chain/call-logs",AI_SYSTEM:"/sf-chain/system"}},es}catch(e){return console.warn("Failed to fetch API config, using defaults:",e),es={baseUrl:"",endpoints:{AI_MODELS:"/sf-chain/models",AI_OPERATIONS:"/sf-chain/operations",AI_CALL_LOGS:"/sf-chain/call-logs",AI_SYSTEM:"/sf-chain/system"}},es}}const Me={BASE_URL:""};function Lo(){return localStorage.getItem("token")}function gu(e){localStorage.setItem("token",e)}function mu(){localStorage.removeItem("token"),localStorage.removeItem("userInfo")}function yu(){mu(),We.error({title:"认证失败",message:"请检查您的token是否正确",duration:4e3})}function bu(){We.error({title:"需要认证",message:"请在页面顶部输入有效的token",duration:4e3})}async function _u(e,t={}){const{method:s="GET",headers:n={},body:o,signal:r,requireAuth:l=!0,isAIRequest:a=!1}=t,c={"Content-Type":"application/json",...n},d=a||e.includes("/sf-chain/");if(d||l){const u=Lo();if(u)c.Authorization=`${u}`;else throw bu(),new Error("未提供认证token");d&&(console.log("🔍 AI请求调试信息:"),console.log("URL:",e),console.log("Authorization Token:",u),console.log("请求头:",c))}try{console.log("📤 发送请求:",{url:e,method:s,headers:c});const u=await fetch(e,{method:s,headers:c,body:o,signal:r});if(u.status===401)throw d?We.error({title:"AI接口认证失败",message:"缺少Authorization请求头",duration:4e3}):yu(),new Error("认证失败");if(u.status===403)throw d?We.error({title:"AI接口权限不足",message:"Authorization验证失败",duration:4e3}):We.error({title:"权限不足",message:"您没有权限执行此操作",duration:4e3}),new Error("权限不足");if(u.status===404)throw We.error({title:"资源不存在",message:"请求的资源不存在或已被删除",duration:3e3}),new Error("资源不存在");if(u.status>=500)throw We.error({title:"服务器错误",message:"服务器暂时无法处理您的请求,请稍后重试",duration:5e3,closable:!0}),new Error("服务器错误");return u}catch(u){const f=u;throw f.name==="TypeError"&&f.message.includes("fetch")?We.error({title:"网络连接失败",message:"无法连接到服务器,请检查网络连接",duration:5e3,closable:!0}):f.name==="AbortError"?console.log("请求已取消"):!f.message.includes("认证失败")&&!f.message.includes("权限不足")&&!f.message.includes("资源不存在")&&!f.message.includes("未提供认证token")&&We.error({title:"请求失败",message:f.message||"请求处理失败,请稍后重试",duration:4e3}),u}}async function Oe(e,t={}){const s=await _u(e,t);if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);try{return await s.json()}catch{throw We.error({title:"数据解析失败",message:"服务器返回的数据格式有误",duration:3e3}),new Error("数据解析失败")}}const Jt=class Jt{constructor(){gs(this,"baseUrl","")}static getInstance(){return Jt.instance||(Jt.instance=new Jt),Jt.instance}async initialize(){const t=await vu();this.baseUrl=t.baseUrl}async request(t,s={}){this.baseUrl||await this.initialize();const n=`${this.baseUrl}${t}`,o=await fetch(n,{headers:{"Content-Type":"application/json",...s.headers},...s});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);return o.json()}async get(t){return this.request(t,{method:"GET"})}async post(t,s){return this.request(t,{method:"POST",body:s?JSON.stringify(s):void 0})}async put(t,s){return this.request(t,{method:"PUT",body:s?JSON.stringify(s):void 0})}async delete(t){return this.request(t,{method:"DELETE"})}};gs(Jt,"instance");let co=Jt;const wu=co.getInstance(),ku={class:"header-bar"},xu={class:"header-content"},Cu={class:"header-right"},$u={class:"auth-section"},Su={class:"status-label"},Tu={class:"auth-controls"},Eu={class:"token-input-group"},Au={class:"input-actions"},Mu=["disabled"],Ou=["disabled"],Pu=at({__name:"HeaderBar",props:{onRefresh:{type:Function,default:()=>{}}},setup(e){const t=e,s=Z(""),n=Z(Lo()),o=()=>{if(!s.value.trim()){We.error({title:"输入错误",message:"请输入有效的访问令牌",duration:3e3});return}gu(s.value.trim()),n.value=s.value.trim(),s.value="",We.success({title:"令牌已保存",message:"访问令牌已成功保存并生效",duration:3e3}),r()},r=async()=>{if(!n.value){We.error({title:"未设置令牌",message:"请先设置访问令牌",duration:3e3});return}try{await t.onRefresh(),We.success({title:"数据已刷新",message:"系统数据已成功更新",duration:3e3})}catch(l){console.error("Refresh data error:",l)}};return(l,a)=>(w(),E("div",ku,[i("div",xu,[a[4]||(a[4]=Oo('

SF-Chain

AI智能调度框架

',1)),i("div",Cu,[i("div",$u,[i("div",{class:be(["connection-status",{connected:n.value}])},[a[1]||(a[1]=i("div",{class:"status-indicator"},[i("div",{class:"status-pulse"})],-1)),i("span",Su,U(n.value?"已连接":"未连接"),1)],2),i("div",Tu,[i("div",Eu,[$e(i("input",{"onUpdate:modelValue":a[0]||(a[0]=c=>s.value=c),type:"password",class:"token-input",placeholder:"输入访问令牌",onKeyup:cl(o,["enter"])},null,544),[[qe,s.value]]),i("div",Au,[i("button",{class:"action-btn save-btn",onClick:o,disabled:!s.value.trim(),title:"保存令牌"},a[2]||(a[2]=[i("svg",{viewBox:"0 0 20 20",fill:"currentColor"},[i("path",{"fill-rule":"evenodd",d:"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z","clip-rule":"evenodd"})],-1)]),8,Mu),i("button",{class:"action-btn refresh-btn",onClick:r,disabled:!n.value,title:"刷新数据"},a[3]||(a[3]=[i("svg",{viewBox:"0 0 20 20",fill:"currentColor"},[i("path",{"fill-rule":"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z","clip-rule":"evenodd"})],-1)]),8,Ou)])])])])])])]))}}),Ru=At(Pu,[["__scopeId","data-v-677538a9"]]),ks={async getAllModels(){return Oe(`${Me.BASE_URL}/sf-chain/models/list`,{method:"GET",requireAuth:!0})},async getModel(e){return Oe(`${Me.BASE_URL}/sf-chain/models/get`,{method:"POST",body:JSON.stringify({modelName:e}),requireAuth:!0})},async saveModel(e,t){return Oe(`${Me.BASE_URL}/sf-chain/models/save`,{method:"POST",body:JSON.stringify({...t,modelName:e}),requireAuth:!0})},async deleteModel(e){return Oe(`${Me.BASE_URL}/sf-chain/models/delete`,{method:"POST",body:JSON.stringify({modelName:e}),requireAuth:!0})},async testModel(e){return Oe(`${Me.BASE_URL}/sf-chain/models/test`,{method:"POST",body:JSON.stringify({modelName:e}),requireAuth:!0})}},Zt={openai:{key:"openai",name:"OpenAI",icon:"/icons/openai.svg",displayOrder:1,category:"commercial",description:"OpenAI GPT系列模型",defaultConfig:{baseUrl:"https://api.openai.com/v1",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1}},anthropic:{key:"anthropic",name:"Anthropic",icon:"/icons/anthropic.svg",displayOrder:2,category:"commercial",description:"Anthropic Claude系列模型",defaultConfig:{baseUrl:"https://api.anthropic.com/v1",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!0}},google:{key:"google",name:"Google",icon:"/icons/google.svg",displayOrder:3,category:"commercial",description:"Google Gemini系列模型",defaultConfig:{baseUrl:"https://generativelanguage.googleapis.com/v1",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1}},deepseek:{key:"deepseek",name:"DeepSeek",icon:"/icons/deepseek.svg",displayOrder:4,category:"domestic",description:"DeepSeek系列模型",defaultConfig:{baseUrl:"https://api.deepseek.com/v1",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!0}},doubao:{key:"doubao",name:"豆包",icon:"/icons/doubao.svg",displayOrder:5,category:"domestic",description:"字节跳动豆包系列模型",defaultConfig:{baseUrl:"https://ark.cn-beijing.volces.com/api/v3",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1}},qianwen:{key:"qianwen",name:"千问",icon:"/icons/qianwen.svg",displayOrder:6,category:"domestic",description:"阿里云千问系列模型",defaultConfig:{baseUrl:"https://dashscope.aliyuncs.com/api/v1",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1}},other:{key:"other",name:"其他",icon:"/icons/default.svg",displayOrder:999,category:"custom",description:"自定义或其他提供商",defaultConfig:{baseUrl:"",maxTokens:4096,temperature:.7,supportStream:!0,supportJsonOutput:!1,supportThinking:!1}}},Qt=e=>{var t;return((t=Zt[e])==null?void 0:t.name)||Zt.other.name},cs=e=>{var t;return((t=Zt[e])==null?void 0:t.icon)||Zt.other.icon},Rs=e=>{const t=e.toLowerCase();return t.includes("gpt")||t.includes("openai")?"openai":t.includes("claude")||t.includes("anthropic")?"anthropic":t.includes("gemini")||t.includes("google")?"google":t.includes("deepseek")?"deepseek":t.includes("doubao")||t.includes("豆包")?"doubao":t.includes("qwen")||t.includes("千问")||t.includes("qianwen")?"qianwen":"other"},dl=()=>Object.values(Zt).sort((e,t)=>e.displayOrder-t.displayOrder),Lu=()=>{const e={};return dl().forEach(s=>{const n=s.category||"other";e[n]||(e[n]=[]),e[n].push(s)}),e},Iu=e=>{var t;return((t=Zt[e])==null?void 0:t.defaultConfig)||Zt.other.defaultConfig},Nu=e=>({commercial:"商业模型",domestic:"国产模型",custom:"自定义",other:"其他"})[e]||e,ju=()=>dl().map(e=>e.key),Bu={class:"api-config-content"},Uu={class:"content-header"},Hu={class:"header-actions"},Du=["disabled"],Vu={key:0,class:"w-4 h-4 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},Fu={key:1,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},qu={key:0,class:"stats-section"},Ku={class:"stat-content"},zu={class:"stat-number"},Gu=["onClick"],Ju={class:"stat-content"},Wu={class:"stat-number"},Qu={class:"stat-label"},Yu={class:"stat-icon"},Zu=["src"],Xu={class:"main-content"},ed={key:0,class:"loading-state"},td={key:1,class:"empty-state"},sd={key:2,class:"models-list"},nd={class:"list-header"},od={class:"header-info"},rd={class:"search-box"},id={class:"models-container"},ld={class:"model-cell"},ad={class:"model-identity"},cd=["onClick"],ud=["src"],dd={class:"model-info"},fd=["title","onClick"],pd={class:"base-url-cell"},hd=["title","onClick"],vd={class:"params-cell"},gd={class:"params-text"},md={class:"description-cell"},yd=["title"],bd={class:"status-cell"},_d={class:"actions-cell"},wd={class:"action-buttons"},kd=["onClick","disabled","title"],xd={key:0,class:"w-4 h-4 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},Cd={key:1,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},$d=["onClick"],Sd=["onClick"],Td=["onClick"],Ed={class:"modal-header"},Ad={class:"form-grid"},Md={class:"form-column"},Od={class:"form-group"},Pd=["disabled"],Rd={class:"form-group"},Ld=["label"],Id=["value"],Nd={class:"form-group"},jd={class:"form-row"},Bd={class:"form-group"},Ud={class:"form-group"},Hd={class:"form-column"},Dd={class:"form-group"},Vd={class:"input-wrapper"},Fd=["type"],qd={key:0,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},Kd={key:1,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},zd={class:"form-group"},Gd={class:"form-group"},Jd={class:"form-actions"},Wd=["disabled"],Qd={key:0,class:"btn-loading"},Yd={key:2,class:"copy-toast"},Zd=at({__name:"ApiInfoConfig",setup(e){const t=Z(!1),s=Z(!1),n=Z(null),o=Z(!1),r=Z(null),l=Z(!1),a=Z(null),c=Z(""),d=Z("all"),u=Z(!1),f=hs({modelName:"",baseUrl:"",apiKey:"",defaultMaxTokens:4096,defaultTemperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1,description:"",provider:"openai",enabled:!0}),v=ve(()=>{var _;if(!((_=a.value)!=null&&_.models))return{};let k={...a.value.models};if(d.value!=="all"&&(k=Object.fromEntries(Object.entries(k).filter(([,B])=>B.provider===d.value))),c.value){const B=c.value.toLowerCase();k=Object.fromEntries(Object.entries(k).filter(([,ne])=>{var oe,ae;return ne.modelName.toLowerCase().includes(B)||((oe=ne.provider)==null?void 0:oe.toLowerCase().includes(B))||ne.baseUrl.toLowerCase().includes(B)||((ae=ne.description)==null?void 0:ae.toLowerCase().includes(B))}))}return k}),g=ve(()=>{var B;if(!((B=a.value)!=null&&B.groupedByProvider))return[];const k=[],_=ju();for(const ne of _)a.value.groupedByProvider[ne]&&k.push({provider:ne,models:a.value.groupedByProvider[ne]});for(const[ne,oe]of Object.entries(a.value.groupedByProvider))_.includes(ne)||k.push({provider:ne,models:oe});return k}),x=ve(()=>Lu()),L=k=>cs(k),J=()=>d.value==="all"?"全部模型":`${Qt(d.value)}模型`,j=k=>{d.value=k,c.value=""},V=()=>{const k=Iu(f.provider);k&&(f.baseUrl||(f.baseUrl=k.baseUrl||""),f.defaultMaxTokens||(f.defaultMaxTokens=k.maxTokens||4096),f.defaultTemperature||(f.defaultTemperature=k.temperature||.7),f.supportStream=k.supportStream??!0,f.supportJsonOutput=k.supportJsonOutput??!0,f.supportThinking=k.supportThinking??!1)},T=async k=>{try{await navigator.clipboard.writeText(k),u.value=!0,setTimeout(()=>{u.value=!1},2e3)}catch(_){console.error("复制失败:",_);const B=document.createElement("textarea");B.value=k,document.body.appendChild(B),B.select(),document.execCommand("copy"),document.body.removeChild(B),u.value=!0,setTimeout(()=>{u.value=!1},2e3)}},y=()=>{Object.assign(f,{modelName:"",baseUrl:"",apiKey:"",defaultMaxTokens:4096,defaultTemperature:.7,supportStream:!0,supportJsonOutput:!0,supportThinking:!1,description:"",provider:"openai",enabled:!0})},P=async()=>{try{t.value=!0,a.value=await ks.getAllModels()}catch(k){console.error("加载模型列表失败:",k),alert("加载模型列表失败,请稍后重试")}finally{t.value=!1}},I=async()=>{try{s.value=!0;const k=await ks.saveModel(f.modelName,f);k.success?(alert(k.message||"模型保存成功"),te(),await P()):alert(k.message||"保存失败")}catch(k){console.error("保存模型失败:",k),alert("保存模型失败,请稍后重试")}finally{s.value=!1}},C=(k,_)=>{Object.assign(f,{..._,modelName:""}),r.value=null,o.value=!0},$=(k,_)=>{r.value=k,Object.assign(f,_),o.value=!1},O=async k=>{if(confirm(`确定要删除模型 "${k}" 吗?`))try{const _=await ks.deleteModel(k);_.success?(alert(_.message||"删除成功"),await P()):alert(_.message||"删除失败")}catch(_){console.error("删除模型失败:",_),alert("删除模型失败,请稍后重试")}},W=async k=>{try{n.value=k;const _=await ks.testModel(k);_.success?alert("模型连接测试成功!"):alert(`测试失败: ${_.message}`)}catch(_){console.error("测试模型失败:",_),alert("测试模型失败,请稍后重试")}finally{n.value=null}},te=()=>{o.value=!1,r.value=null,y(),l.value=!1};return Dt(()=>{P()}),(k,_)=>(w(),E("div",Bu,[i("div",Uu,[_[17]||(_[17]=i("div",{class:"header-left"},[i("h2",null,"AI模型")],-1)),i("div",Hu,[i("button",{onClick:P,class:"btn btn-secondary",disabled:t.value},[t.value?(w(),E("svg",Vu,_[14]||(_[14]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))):(w(),E("svg",Fu,_[15]||(_[15]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))),i("span",null,U(t.value?"加载中":"刷新"),1)],8,Du),i("button",{onClick:_[0]||(_[0]=B=>o.value=!0),class:"btn btn-primary"},_[16]||(_[16]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"})],-1),i("span",null,"添加模型",-1)]))])]),a.value?(w(),E("div",qu,[i("div",{class:be(["stat-card",{active:d.value==="all"}]),onClick:_[1]||(_[1]=B=>j("all"))},[i("div",Ku,[i("div",zu,U(a.value.total),1),_[18]||(_[18]=i("div",{class:"stat-label"},"全部模型",-1))])],2),(w(!0),E(ye,null,Le(g.value,({provider:B,models:ne})=>(w(),E("div",{class:be(["stat-card",{active:d.value===B}]),key:B,onClick:oe=>j(B)},[i("div",Ju,[i("div",Wu,U(ne.length),1),i("div",Qu,U(Ee(Qt)(B)),1)]),i("div",Yu,[i("img",{src:Ee(cs)(B),alt:"provider icon",class:"stat-provider-icon"},null,8,Zu)])],10,Gu))),128))])):le("",!0),i("div",Xu,[t.value&&!a.value?(w(),E("div",ed,_[19]||(_[19]=[i("div",{class:"loading-spinner"},null,-1),i("p",null,"正在加载模型配置...",-1)]))):a.value&&a.value.total===0?(w(),E("div",td,_[20]||(_[20]=[i("div",{class:"empty-icon"},"🤖",-1),i("h3",null,"暂无模型配置",-1),i("p",null,'点击"添加模型"按钮开始配置您的第一个AI模型',-1)]))):(w(),E("div",sd,[i("div",nd,[i("div",od,[i("h3",null,U(J())+" ("+U(Object.keys(v.value).length)+")",1),i("div",rd,[_[22]||(_[22]=i("svg",{class:"search-icon",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})],-1)),$e(i("input",{"onUpdate:modelValue":_[2]||(_[2]=B=>c.value=B),type:"text",placeholder:"搜索模型...",class:"search-input"},null,512),[[qe,c.value]]),c.value?(w(),E("button",{key:0,onClick:_[3]||(_[3]=B=>c.value=""),class:"clear-search"},_[21]||(_[21]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)]))):le("",!0)])])]),_[28]||(_[28]=Oo('
模型信息
Base URL
Token/温度
描述
状态
操作
',1)),i("div",id,[(w(!0),E(ye,null,Le(v.value,(B,ne)=>(w(),E("div",{key:ne,class:be(["model-row",{disabled:!B.enabled}])},[i("div",ld,[i("div",ad,[i("div",{class:"model-avatar",title:"点击复制图标",onClick:oe=>T(L(B.provider||"other"))},[i("img",{src:Ee(cs)(B.provider||"other"),alt:"provider icon",class:"provider-icon"},null,8,ud)],8,cd),i("div",dd,[i("h4",{class:"model-name",title:"点击复制: "+B.modelName,onClick:oe=>T(B.modelName)},U(B.modelName),9,fd),i("span",{class:be(["provider-badge",B.provider])},U(Ee(Qt)(B.provider||"other")),3)])])]),i("div",pd,[i("span",{class:"base-url-text",title:"点击复制: "+B.baseUrl,onClick:oe=>T(B.baseUrl)},U(B.baseUrl),9,hd)]),i("div",vd,[i("span",gd,U(B.defaultMaxTokens||"N/A")+" / "+U(B.defaultTemperature||"N/A"),1)]),i("div",md,[i("span",{class:"description-text",title:B.description},U(B.description||"-"),9,yd)]),i("div",bd,[i("span",{class:be(["status-badge",{enabled:B.enabled,disabled:!B.enabled}])},U(B.enabled?"启用":"禁用"),3)]),i("div",_d,[i("div",wd,[i("button",{onClick:oe=>W(String(ne)),class:"action-btn test",disabled:n.value===ne,title:n.value===ne?"测试中...":"测试连接"},[n.value===ne?(w(),E("svg",xd,_[23]||(_[23]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))):(w(),E("svg",Cd,_[24]||(_[24]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"},null,-1)])))],8,kd),i("button",{onClick:oe=>C(String(ne),B),class:"action-btn clone",title:"克隆模型"},_[25]||(_[25]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"})],-1)]),8,$d),i("button",{onClick:oe=>$(String(ne),B),class:"action-btn edit",title:"编辑模型"},_[26]||(_[26]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"})],-1)]),8,Sd),i("button",{onClick:oe=>O(String(ne)),class:"action-btn delete",title:"删除模型"},_[27]||(_[27]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"})],-1)]),8,Td)])])],2))),128))])]))]),o.value||r.value?(w(),E("div",{key:1,class:"modal-overlay",onClick:te},[i("div",{class:"modal-content",onClick:_[13]||(_[13]=Ps(()=>{},["stop"]))},[i("div",Ed,[i("h3",null,U(r.value?"编辑模型":"添加模型"),1),i("button",{onClick:te,class:"btn-close"},_[29]||(_[29]=[i("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)]))]),i("form",{onSubmit:Ps(I,["prevent"]),class:"modal-body"},[i("div",Ad,[i("div",Md,[i("div",Od,[_[30]||(_[30]=i("label",{for:"modelName"},"模型名称 *",-1)),$e(i("input",{id:"modelName","onUpdate:modelValue":_[4]||(_[4]=B=>f.modelName=B),type:"text",placeholder:"例如: gpt-4o",class:"form-input",required:"",disabled:!!r.value},null,8,Pd),[[qe,f.modelName]])]),i("div",Rd,[_[31]||(_[31]=i("label",{for:"provider"},"提供商",-1)),$e(i("select",{id:"provider","onUpdate:modelValue":_[5]||(_[5]=B=>f.provider=B),class:"form-input",onChange:V},[(w(!0),E(ye,null,Le(x.value,(B,ne)=>(w(),E("optgroup",{key:ne,label:Ee(Nu)(ne)},[(w(!0),E(ye,null,Le(B,oe=>(w(),E("option",{key:oe.key,value:oe.key},U(oe.name),9,Id))),128))],8,Ld))),128))],544),[[vt,f.provider]])]),i("div",Nd,[_[32]||(_[32]=i("label",{for:"baseUrl"},"Base URL *",-1)),$e(i("input",{id:"baseUrl","onUpdate:modelValue":_[6]||(_[6]=B=>f.baseUrl=B),type:"url",placeholder:"https://api.openai.com/v1",class:"form-input",required:""},null,512),[[qe,f.baseUrl]])]),i("div",jd,[i("div",Bd,[_[33]||(_[33]=i("label",{for:"maxTokens"},"Token数",-1)),$e(i("input",{id:"maxTokens","onUpdate:modelValue":_[7]||(_[7]=B=>f.defaultMaxTokens=B),type:"number",placeholder:"4096",class:"form-input"},null,512),[[qe,f.defaultMaxTokens,void 0,{number:!0}]])]),i("div",Ud,[_[34]||(_[34]=i("label",{for:"temperature"},"温度",-1)),$e(i("input",{id:"temperature","onUpdate:modelValue":_[8]||(_[8]=B=>f.defaultTemperature=B),type:"number",step:"0.1",min:"0",max:"2",placeholder:"0.7",class:"form-input"},null,512),[[qe,f.defaultTemperature,void 0,{number:!0}]])])])]),i("div",Hd,[i("div",Dd,[_[37]||(_[37]=i("label",{for:"apiKey"},"API Key *",-1)),i("div",Vd,[$e(i("input",{id:"apiKey","onUpdate:modelValue":_[9]||(_[9]=B=>f.apiKey=B),type:l.value?"text":"password",placeholder:"请输入API Key",class:"form-input",required:""},null,8,Fd),[[Jc,f.apiKey]]),i("button",{onClick:_[10]||(_[10]=B=>l.value=!l.value),class:"toggle-visibility",type:"button"},[l.value?(w(),E("svg",qd,_[35]||(_[35]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"},null,-1),i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"},null,-1)]))):(w(),E("svg",Kd,_[36]||(_[36]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"},null,-1)])))])])]),i("div",zd,[_[39]||(_[39]=i("label",{for:"enabled"},"状态",-1)),$e(i("select",{id:"enabled","onUpdate:modelValue":_[11]||(_[11]=B=>f.enabled=B),class:"form-input"},_[38]||(_[38]=[i("option",{value:!0},"启用",-1),i("option",{value:!1},"禁用",-1)]),512),[[vt,f.enabled]])]),i("div",Gd,[_[40]||(_[40]=i("label",{for:"description"},"描述",-1)),$e(i("textarea",{id:"description","onUpdate:modelValue":_[12]||(_[12]=B=>f.description=B),placeholder:"模型描述信息",class:"form-textarea",rows:"3"},null,512),[[qe,f.description]])])])]),i("div",Jd,[i("button",{type:"button",onClick:te,class:"btn btn-secondary"}," 取消 "),i("button",{type:"submit",class:"btn btn-primary",disabled:s.value},[s.value?(w(),E("span",Qd)):le("",!0),i("span",null,U(s.value?"保存中...":"保存"),1)],8,Wd)])],32)])])):le("",!0),u.value?(w(),E("div",Yd,_[41]||(_[41]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"})],-1),Pe(" 复制成功 ")]))):le("",!0)]))}}),Xd=At(Zd,[["__scopeId","data-v-48fd4b43"]]),tn={async getAllOperations(){return Oe(`${Me.BASE_URL}/sf-chain/operations`,{method:"GET",requireAuth:!0})},async getOperation(e){return Oe(`${Me.BASE_URL}/sf-chain/operations/get`,{method:"POST",body:JSON.stringify({operationType:e}),requireAuth:!0})},async saveOperationConfig(e,t){const s={...t,operationType:e};return Oe(`${Me.BASE_URL}/sf-chain/operations/save`,{method:"POST",body:JSON.stringify(s),requireAuth:!0})},async setOperationMapping(e,t){return Oe(`${Me.BASE_URL}/sf-chain/operations/mapping`,{method:"POST",body:JSON.stringify({operationType:e,modelName:t}),requireAuth:!0})},async setOperationMappings(e){return Oe(`${Me.BASE_URL}/sf-chain/operations/mappings`,{method:"POST",body:JSON.stringify({mappings:e}),requireAuth:!0})}},ef={class:"ai-node-config-content"},tf={class:"content-header"},sf={class:"header-right"},nf={key:0,class:"header-stats"},of={class:"stat-item"},rf={class:"stat-number"},lf={class:"stat-item success"},af={class:"stat-number"},cf={class:"stat-item warning"},uf={class:"stat-number"},df={class:"stat-item info"},ff={class:"stat-number"},pf={class:"header-actions"},hf=["disabled"],vf={key:0,class:"w-4 h-4 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},gf={key:1,class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},mf={class:"toolbar"},yf={class:"search-container"},bf={class:"filter-tabs"},_f={class:"count"},wf={class:"count"},kf={class:"count"},xf={class:"main-content"},Cf={key:0,class:"loading-state"},$f={key:1,class:"empty-state"},Sf={key:2,class:"operations-grid"},Tf={class:"card-header"},Ef={class:"operation-info"},Af={class:"operation-icon"},Mf=["src"],Of={key:1,class:"default-icon"},Pf={class:"operation-details"},Rf={class:"operation-name"},Lf={class:"operation-desc"},If={class:"model-binding"},Nf={class:"model-selector"},jf=["onUpdate:modelValue","onChange"],Bf=["label"],Uf=["value"],Hf={key:0,class:"config-summary"},Df={class:"config-item"},Vf={class:"config-value"},Ff={class:"config-item"},qf={class:"config-value"},Kf={class:"config-item"},zf={class:"config-value"},Gf={class:"config-features"},Jf={key:0,class:"feature-tag json"},Wf={key:1,class:"feature-tag thinking"},Qf={class:"card-actions"},Yf=["onClick","disabled","title"],Zf={key:0,class:"w-5 h-5 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},Xf={key:1,class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},ep=["onClick"],tp={class:"modal-body compact"},sp={class:"form-row"},np={class:"form-group"},op=["label"],rp=["value"],ip={class:"form-group"},lp={class:"operation-checkboxes"},ap=["value"],cp={class:"checkbox-label"},up={class:"form-actions"},dp=["disabled"],fp={key:0,class:"btn-loading"},pp={class:"modal-header"},hp={class:"form-grid wide"},vp={class:"form-group"},gp=["label"],mp=["value"],yp={class:"form-group"},bp={class:"form-group"},_p={class:"form-group"},wp={class:"form-group checkbox-group"},kp={class:"checkbox-label"},xp={class:"form-group checkbox-group"},Cp={class:"checkbox-label"},$p={class:"form-group full-width"},Sp={class:"form-actions"},Tp=["disabled"],Ep={key:0,class:"btn-loading"},Ap={key:2,class:"success-toast"},Mp={key:3,class:"error-toast"},Op=at({__name:"AiNodeConfig",setup(e){const t=Z(!1),s=Z(!1),n=Z(!1),o=Z(null),r=Z(!1),l=Z(null),a=Z(""),c=Z(""),d=Z("all"),u=Z(!1),f=Z(!1),v=Z(""),g=Z([]),x=Z(null),L=Z(""),J=Z([]),j=hs({operationType:"",description:"",enabled:!0,maxTokens:4096,temperature:.7,jsonOutput:!1,thinkingMode:!1,customParams:{},modelName:""}),V=ve(()=>g.value.filter(G=>G.enabled)),T=ve(()=>{const G={};return V.value.forEach(b=>{const ue=b.provider||"other";G[ue]||(G[ue]=[]),G[ue].push(b)}),G}),y=ve(()=>{var b;if(!((b=x.value)!=null&&b.configs))return{};let G={...x.value.configs};if(c.value){const ue=c.value.toLowerCase();G=Object.fromEntries(Object.entries(G).filter(([Y,me])=>{var Se;return Y.toLowerCase().includes(ue)||((Se=me.description)==null?void 0:Se.toLowerCase().includes(ue))}))}return d.value==="configured"?G=Object.fromEntries(Object.entries(G).filter(([,ue])=>ue.modelName)):d.value==="pending"&&(G=Object.fromEntries(Object.entries(G).filter(([,ue])=>!ue.modelName))),G}),P=ve(()=>{var G;return(G=x.value)!=null&&G.configs?Object.values(x.value.configs).filter(b=>b.modelName).length:0}),I=ve(()=>{var G;return(G=x.value)!=null&&G.configs?Object.values(x.value.configs).filter(b=>!b.modelName).length:0}),C=G=>{const b=g.value.find(ue=>ue.modelName===G);return(b==null?void 0:b.provider)||"other"},$=G=>Qt(G),O=G=>G.enabled?G.modelName?"configured":"pending":"disabled",W=G=>G.enabled?G.modelName?"已配置":"待配置":"已禁用",te=async()=>{try{t.value=!0;const[G,b]=await Promise.all([ks.getAllModels(),tn.getAllOperations()]);g.value=Object.values(G.models||{}).map(ue=>({modelName:ue.modelName,provider:ue.provider||"other",enabled:ue.enabled??!0})),x.value=b}catch(G){console.error("加载数据失败:",G),Ae("加载数据失败,请稍后重试","error")}finally{t.value=!1}},k=async G=>{try{o.value=G,await new Promise(b=>setTimeout(b,2e3)),Ae("测试成功")}catch(b){console.error("测试失败:",b),Ae("测试失败,请检查配置","error")}finally{o.value=null}},_=async(G,b)=>{try{await tn.setOperationMapping(G,b),Ae("映射更新成功"),await te()}catch(ue){console.error("更新映射失败:",ue),Ae("更新映射失败,请稍后重试","error")}},B=(G,b)=>{a.value=G,l.value=b,Object.assign(j,{...b,operationType:G})},ne=()=>{l.value=null,a.value=""},oe=async()=>{try{s.value=!0,await tn.saveOperationConfig(a.value,j),Ae("配置保存成功"),ne(),await te()}catch(G){console.error("保存配置失败:",G),Ae("保存失败: "+(G.message||"未知错误"),"error")}finally{s.value=!1}},ae=()=>{r.value=!1,L.value="",J.value=[]},ce=async()=>{try{n.value=!0;const G={};J.value.forEach(b=>{G[b]=L.value}),await tn.setOperationMappings(G),Ae("批量配置成功"),ae(),await te()}catch(G){console.error("批量配置失败:",G),Ae("批量配置失败: "+(G.message||"未知错误"),"error")}finally{n.value=!1}},Ae=(G,b="success")=>{v.value=G,b==="success"?(u.value=!0,setTimeout(()=>{u.value=!1},3e3)):(f.value=!0,setTimeout(()=>{f.value=!1},3e3))};return te(),(G,b)=>{var ue;return w(),E("div",ef,[i("div",tf,[b[24]||(b[24]=i("div",{class:"header-left"},[i("h2",null,"AI节点")],-1)),i("div",sf,[x.value?(w(),E("div",nf,[i("div",of,[i("span",rf,U(x.value.totalOperations),1),b[17]||(b[17]=i("span",{class:"stat-label"},"总节点",-1))]),i("div",lf,[i("span",af,U(P.value),1),b[18]||(b[18]=i("span",{class:"stat-label"},"已配置",-1))]),i("div",cf,[i("span",uf,U(I.value),1),b[19]||(b[19]=i("span",{class:"stat-label"},"待配置",-1))]),i("div",df,[i("span",ff,U(V.value.length),1),b[20]||(b[20]=i("span",{class:"stat-label"},"可用模型",-1))])])):le("",!0),i("div",pf,[i("button",{onClick:te,class:"btn btn-secondary",disabled:t.value},[t.value?(w(),E("svg",vf,b[21]||(b[21]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))):(w(),E("svg",gf,b[22]||(b[22]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))),i("span",null,U(t.value?"加载中":"刷新"),1)],8,hf),i("button",{onClick:b[0]||(b[0]=Y=>r.value=!0),class:"btn btn-primary"},b[23]||(b[23]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4"})],-1),i("span",null,"批量配置",-1)]))])])]),i("div",mf,[i("div",yf,[b[26]||(b[26]=i("svg",{class:"search-icon",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})],-1)),$e(i("input",{"onUpdate:modelValue":b[1]||(b[1]=Y=>c.value=Y),type:"text",placeholder:"搜索节点...",class:"search-input"},null,512),[[qe,c.value]]),c.value?(w(),E("button",{key:0,onClick:b[2]||(b[2]=Y=>c.value=""),class:"clear-btn"},b[25]||(b[25]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)]))):le("",!0)]),i("div",bf,[i("button",{onClick:b[3]||(b[3]=Y=>d.value="all"),class:be(["filter-tab",{active:d.value==="all"}])},[b[27]||(b[27]=Pe(" 全部 ")),i("span",_f,U(Object.keys(y.value).length),1)],2),i("button",{onClick:b[4]||(b[4]=Y=>d.value="configured"),class:be(["filter-tab",{active:d.value==="configured"}])},[b[28]||(b[28]=Pe(" 已配置 ")),i("span",wf,U(P.value),1)],2),i("button",{onClick:b[5]||(b[5]=Y=>d.value="pending"),class:be(["filter-tab",{active:d.value==="pending"}])},[b[29]||(b[29]=Pe(" 待配置 ")),i("span",kf,U(I.value),1)],2)])]),i("div",xf,[t.value&&!x.value?(w(),E("div",Cf,b[30]||(b[30]=[i("div",{class:"loading-spinner"},null,-1),i("p",null,"正在加载节点配置...",-1)]))):x.value&&x.value.totalOperations===0?(w(),E("div",$f,b[31]||(b[31]=[i("div",{class:"empty-icon"},"🤖",-1),i("h3",null,"暂无AI操作节点",-1),i("p",null,"系统中还没有注册任何AI操作节点",-1)]))):(w(),E("div",Sf,[(w(!0),E(ye,null,Le(y.value,(Y,me)=>(w(),E("div",{key:me,class:be(["operation-card",{configured:Y.modelName,disabled:!Y.enabled,testing:o.value===me}])},[i("div",Tf,[i("div",Ef,[i("div",Af,[Y.modelName?(w(),E("img",{key:0,src:Ee(cs)(C(Y.modelName)),alt:"provider",class:"provider-icon-large"},null,8,Mf)):(w(),E("div",Of,"🤖"))]),i("div",Pf,[i("h4",Rf,U(String(me)),1),i("p",Lf,U(Y.description||"无描述"),1)])]),i("div",{class:be(["status-badge",O(Y)])},U(W(Y)),3)]),i("div",If,[i("div",Nf,[$e(i("select",{"onUpdate:modelValue":Se=>Y.modelName=Se,onChange:Se=>_(String(me),Y.modelName||""),class:be(["model-select",{"has-value":Y.modelName}])},[b[32]||(b[32]=i("option",{value:""},"选择模型",-1)),(w(!0),E(ye,null,Le(T.value,(Se,He)=>(w(),E("optgroup",{key:He,label:$(He)},[(w(!0),E(ye,null,Le(Se,S=>(w(),E("option",{key:S.modelName,value:S.modelName},U(S.modelName),9,Uf))),128))],8,Bf))),128))],42,jf),[[vt,Y.modelName]])])]),Y.modelName?(w(),E("div",Hf,[i("div",Df,[b[33]||(b[33]=i("span",{class:"config-label"},"模型:",-1)),i("span",Vf,U(Y.modelName),1)]),i("div",Ff,[b[34]||(b[34]=i("span",{class:"config-label"},"Token:",-1)),i("span",qf,U(Y.maxTokens||4096),1)]),i("div",Kf,[b[35]||(b[35]=i("span",{class:"config-label"},"温度:",-1)),i("span",zf,U(Y.temperature||.7),1)]),i("div",Gf,[Y.jsonOutput?(w(),E("span",Jf,"JSON")):le("",!0),Y.thinkingMode?(w(),E("span",Wf,"思考")):le("",!0)])])):le("",!0),i("div",Qf,[Y.modelName?(w(),E("button",{key:0,onClick:Se=>k(String(me)),class:"action-btn test large",disabled:o.value===me,title:o.value===me?"测试中...":"测试操作"},[o.value===me?(w(),E("svg",Zf,b[36]||(b[36]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))):(w(),E("svg",Xf,b[37]||(b[37]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"},null,-1)])))],8,Yf)):le("",!0),i("button",{onClick:Se=>B(String(me),Y),class:"action-btn edit large",title:"编辑配置"},b[38]||(b[38]=[i("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"})],-1)]),8,ep)])],2))),128))]))]),r.value?(w(),E("div",{key:0,class:"modal-overlay",onClick:ae},[i("div",{class:"modal-content wide",onClick:b[8]||(b[8]=Ps(()=>{},["stop"]))},[i("div",{class:"modal-header"},[b[40]||(b[40]=i("h3",null,"批量配置",-1)),i("button",{onClick:ae,class:"btn-close"},b[39]||(b[39]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)]))]),i("div",tp,[i("div",sp,[i("div",np,[b[42]||(b[42]=i("label",null,"选择默认模型",-1)),$e(i("select",{"onUpdate:modelValue":b[6]||(b[6]=Y=>L.value=Y),class:"form-input"},[b[41]||(b[41]=i("option",{value:""},"选择模型",-1)),(w(!0),E(ye,null,Le(T.value,(Y,me)=>(w(),E("optgroup",{key:me,label:$(me)},[(w(!0),E(ye,null,Le(Y,Se=>(w(),E("option",{key:Se.modelName,value:Se.modelName},U(Se.modelName),9,rp))),128))],8,op))),128))],512),[[vt,L.value]])]),i("div",ip,[b[43]||(b[43]=i("label",null,"选择操作节点",-1)),i("div",lp,[(w(!0),E(ye,null,Le((ue=x.value)==null?void 0:ue.configs,(Y,me)=>(w(),E("label",{key:me,class:"checkbox-item"},[$e(i("input",{type:"checkbox","onUpdate:modelValue":b[7]||(b[7]=Se=>J.value=Se),value:me,class:"checkbox-input"},null,8,ap),[[an,J.value]]),i("span",cp,U(String(me)),1)]))),128))])])]),i("div",up,[i("button",{type:"button",onClick:ae,class:"btn btn-secondary"}," 取消 "),i("button",{onClick:ce,class:"btn btn-primary",disabled:!L.value||J.value.length===0||n.value},[n.value?(w(),E("span",fp)):le("",!0),i("span",null,U(n.value?"应用中...":"应用配置"),1)],8,dp)])])])])):le("",!0),l.value?(w(),E("div",{key:1,class:"modal-overlay",onClick:ne},[i("div",{class:"modal-content wide",onClick:b[16]||(b[16]=Ps(()=>{},["stop"]))},[i("div",pp,[i("h3",null,"配置节点 - "+U(a.value),1),i("button",{onClick:ne,class:"btn-close"},b[44]||(b[44]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)]))]),i("form",{onSubmit:Ps(oe,["prevent"]),class:"modal-body compact"},[i("div",hp,[i("div",vp,[b[46]||(b[46]=i("label",{for:"operationModel"},"绑定模型",-1)),$e(i("select",{id:"operationModel","onUpdate:modelValue":b[9]||(b[9]=Y=>j.modelName=Y),class:"form-input"},[b[45]||(b[45]=i("option",{value:""},"选择模型",-1)),(w(!0),E(ye,null,Le(T.value,(Y,me)=>(w(),E("optgroup",{key:me,label:$(me)},[(w(!0),E(ye,null,Le(Y,Se=>(w(),E("option",{key:Se.modelName,value:Se.modelName},U(Se.modelName),9,mp))),128))],8,gp))),128))],512),[[vt,j.modelName]])]),i("div",yp,[b[48]||(b[48]=i("label",{for:"operationEnabled"},"状态",-1)),$e(i("select",{id:"operationEnabled","onUpdate:modelValue":b[10]||(b[10]=Y=>j.enabled=Y),class:"form-input"},b[47]||(b[47]=[i("option",{value:!0},"启用",-1),i("option",{value:!1},"禁用",-1)]),512),[[vt,j.enabled]])]),i("div",bp,[b[49]||(b[49]=i("label",{for:"operationMaxTokens"},"Token数",-1)),$e(i("input",{id:"operationMaxTokens","onUpdate:modelValue":b[11]||(b[11]=Y=>j.maxTokens=Y),type:"number",placeholder:"4096",class:"form-input"},null,512),[[qe,j.maxTokens,void 0,{number:!0}]])]),i("div",_p,[b[50]||(b[50]=i("label",{for:"operationTemperature"},"温度",-1)),$e(i("input",{id:"operationTemperature","onUpdate:modelValue":b[12]||(b[12]=Y=>j.temperature=Y),type:"number",step:"0.1",min:"0",max:"2",placeholder:"0.7",class:"form-input"},null,512),[[qe,j.temperature,void 0,{number:!0}]])]),i("div",wp,[i("label",kp,[$e(i("input",{type:"checkbox","onUpdate:modelValue":b[13]||(b[13]=Y=>j.jsonOutput=Y),class:"checkbox-input"},null,512),[[an,j.jsonOutput]]),b[51]||(b[51]=i("span",null,"JSON输出",-1))])]),i("div",xp,[i("label",Cp,[$e(i("input",{type:"checkbox","onUpdate:modelValue":b[14]||(b[14]=Y=>j.thinkingMode=Y),class:"checkbox-input"},null,512),[[an,j.thinkingMode]]),b[52]||(b[52]=i("span",null,"思考模式",-1))])]),i("div",$p,[b[53]||(b[53]=i("label",{for:"operationDescription"},"描述",-1)),$e(i("textarea",{id:"operationDescription","onUpdate:modelValue":b[15]||(b[15]=Y=>j.description=Y),placeholder:"操作描述信息",class:"form-textarea",rows:"2"},null,512),[[qe,j.description]])])]),i("div",Sp,[i("button",{type:"button",onClick:ne,class:"btn btn-secondary"}," 取消 "),i("button",{type:"submit",class:"btn btn-primary",disabled:s.value},[s.value?(w(),E("span",Ep)):le("",!0),i("span",null,U(s.value?"保存中...":"保存"),1)],8,Tp)])],32)])])):le("",!0),u.value?(w(),E("div",Ap,[b[54]||(b[54]=i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"})],-1)),Pe(" "+U(v.value),1)])):le("",!0),f.value?(w(),E("div",Mp,[b[55]||(b[55]=i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)),Pe(" "+U(v.value),1)])):le("",!0)])}}}),Pp=At(Op,[["__scopeId","data-v-de75772f"]]),Rp={class:"system-content"},Lp={class:"system-operations"},Ip={class:"operation-card"},Np={class:"card-content"},jp=["disabled"],Bp={key:0,class:"btn-loading"},Up={class:"operation-card"},Hp={class:"card-content"},Dp=["disabled"],Vp={key:0,class:"btn-loading"},Fp={class:"operation-card"},qp={class:"card-content"},Kp=["disabled"],zp={key:0,class:"btn-loading"},qn="/api/sf-chain",Gp=at({__name:"SystemManagement",props:{systemOverview:{}},emits:["update-overview"],setup(e,{emit:t}){const s=t,n=Z(!1),o=Z(!1),r=Z(!1),l=async()=>{n.value=!0;try{const u=await(await fetch(`${qn}/system/backup`,{method:"POST"})).json();if(u.success)alert("系统配置备份创建成功"),u.data&&s("update-overview",u.data);else throw new Error(u.message||"备份失败")}catch(d){const u=d instanceof Error?d.message:"创建备份时出错";alert("备份失败: "+u)}finally{n.value=!1}},a=async()=>{o.value=!0;try{const u=await(await fetch(`${qn}/system/refresh`,{method:"POST"})).json();if(u.success)alert("系统配置刷新成功"),u.data&&s("update-overview",u.data);else throw new Error(u.message||"刷新失败")}catch(d){const u=d instanceof Error?d.message:"刷新系统配置时出错";alert("刷新失败: "+u)}finally{o.value=!1}},c=async()=>{if(confirm("确定要重置系统配置吗?此操作不可撤销!")){r.value=!0;try{const u=await(await fetch(`${qn}/system/reset`,{method:"POST"})).json();if(u.success)alert("系统配置重置成功"),u.data&&s("update-overview",u.data);else throw new Error(u.message||"重置失败")}catch(d){const u=d instanceof Error?d.message:"重置系统配置时出错";alert("重置失败: "+u)}finally{r.value=!1}}};return(d,u)=>(w(),E("div",Rp,[u[9]||(u[9]=i("div",{class:"content-header"},[i("h2",null,"系统管理"),i("p",null,"系统配置备份、刷新和重置操作")],-1)),i("div",Lp,[i("div",Ip,[u[2]||(u[2]=i("div",{class:"card-icon"},[i("span",null,"💾")],-1)),i("div",Np,[u[0]||(u[0]=i("h3",null,"配置备份",-1)),u[1]||(u[1]=i("p",null,"创建当前系统配置的备份文件",-1)),i("button",{onClick:l,class:"btn btn-primary",disabled:n.value},[n.value?(w(),E("span",Bp)):le("",!0),i("span",null,U(n.value?"备份中...":"创建备份"),1)],8,jp)])]),i("div",Up,[u[5]||(u[5]=i("div",{class:"card-icon"},[i("span",null,"🔄")],-1)),i("div",Hp,[u[3]||(u[3]=i("h3",null,"刷新配置",-1)),u[4]||(u[4]=i("p",null,"重新加载系统配置信息",-1)),i("button",{onClick:a,class:"btn btn-secondary",disabled:o.value},[o.value?(w(),E("span",Vp)):le("",!0),i("span",null,U(o.value?"刷新中...":"刷新配置"),1)],8,Dp)])]),i("div",Fp,[u[8]||(u[8]=i("div",{class:"card-icon"},[i("span",null,"⚠️")],-1)),i("div",qp,[u[6]||(u[6]=i("h3",null,"重置系统",-1)),u[7]||(u[7]=i("p",null,"将系统配置重置为默认状态",-1)),i("button",{onClick:c,class:"btn btn-danger",disabled:r.value},[r.value?(w(),E("span",zp)):le("",!0),i("span",null,U(r.value?"重置中...":"重置系统"),1)],8,Kp)])])])]))}}),Jp=At(Gp,[["__scopeId","data-v-038ec4b3"]]),uo={async getAllLogSummaries(){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs`,{method:"GET",requireAuth:!0})},async getFullLog(e){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs/${encodeURIComponent(e)}`,{method:"GET",requireAuth:!0})},async getLogSummariesByOperation(e){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs/operation/${encodeURIComponent(e)}`,{method:"GET",requireAuth:!0})},async getLogSummariesByModel(e){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs/model/${encodeURIComponent(e)}`,{method:"GET",requireAuth:!0})},async getStatistics(){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs/statistics`,{method:"GET",requireAuth:!0})},async clearLogs(){return Oe(`${Me.BASE_URL}/sf-chain/ai-logs`,{method:"DELETE",requireAuth:!0})}},Wp={class:"json-viewer"},Qp={class:"json-toolbar"},Yp={class:"toolbar-left"},Zp={viewBox:"0 0 16 16",fill:"currentColor"},Xp=["d"],eh={key:0,viewBox:"0 0 16 16",fill:"currentColor"},th={key:1,viewBox:"0 0 16 16",fill:"currentColor"},sh={class:"toolbar-center"},nh={key:0,class:"search-box"},oh={class:"toolbar-right"},rh={key:0,class:"path-display"},ih={class:"size-info"},lh={key:1,class:"item-count"},ah={class:"json-content",ref:"jsonContainer"},ch={key:0,class:"json-raw"},uh=["innerHTML"],dh=at({__name:"JsonViewer",props:{data:{type:[String,Number,Boolean,null,Object,Array]},maxHeight:{default:"400px"}},setup(e){Rc(P=>({"1b6c152d":t.maxHeight}));const t=e,s=Z(!0),n=Z(!0),o=Z(new Set),r=Z(""),l=Z(!1),a=Z(""),c=ve(()=>{if(!r.value.trim())return new Set;const P=new Set,I=r.value.toLowerCase(),C=($,O="")=>{$!=null&&(typeof $=="object"&&!Array.isArray($)?Object.entries($).forEach(([W,te])=>{const k=O?`${O}.${W}`:W;W.toLowerCase().includes(I)&&P.add(k),typeof te=="string"&&te.toLowerCase().includes(I)&&P.add(k),C(te,k)}):Array.isArray($)&&$.forEach((W,te)=>{const k=`${O}[${te}]`;typeof W=="string"&&W.toLowerCase().includes(I)&&P.add(k),C(W,k)}))};return C(t.data),P}),d=(P,I="",C=0)=>{if(P===null)return'null';if(P===void 0)return'undefined';const $=typeof P,O=" ".repeat(C),te=c.value.has(I)?" search-highlight":"";if($==="string")return`${u(JSON.stringify(P))}`;if($==="number")return`${P}`;if($==="boolean")return`${P}`;if(Array.isArray(P)){if(P.length===0)return'[]';const k=n.value||o.value.has(I)||c.value.has(I),_=k?"expanded":"collapsed";if(!k)return`[...${P.length}项]`;const B=P.map((ne,oe)=>{const ae=`${I}[${oe}]`;return` +${O} ${d(ne,ae,C+1)}`}).join(",");return`[${B} +${O}]`}if($==="object"&&P!==null){const k=Object.entries(P);if(k.length===0)return'{}';const _=n.value||o.value.has(I)||c.value.has(I),B=_?"expanded":"collapsed";if(!_)return`{...${k.length}键}`;const ne=k.map(([oe,ae])=>{const ce=I?`${I}.${oe}`:oe,Ae=c.value.has(ce)?" search-highlight":"";return` +${O} ${u(JSON.stringify(oe))}: ${d(ae,ce,C+1)}`}).join(",");return`{${ne} +${O}}`}return String(P)},u=P=>P.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'"),f=ve(()=>d(t.data)),v=()=>{s.value=!s.value,s.value||(r.value="")},g=()=>{n.value=!n.value,o.value.clear()},x=async()=>{try{const P=s.value?JSON.stringify(t.data,null,2):JSON.stringify(t.data);await navigator.clipboard.writeText(P),l.value=!0,setTimeout(()=>{l.value=!1},2e3)}catch(P){console.error("复制失败:",P)}},L=()=>{const P=JSON.stringify(t.data),I=new Blob([P]).size;return I<1024?`${I}B`:I<1024*1024?`${(I/1024).toFixed(1)}KB`:`${(I/(1024*1024)).toFixed(1)}MB`},J=()=>`${j(t.data)}项`,j=P=>P==null||typeof P!="object"?1:Array.isArray(P)?P.reduce((I,C)=>I+j(C),0):Object.values(P).reduce((I,C)=>I+j(C),0),V=P=>{const I=P.target;if(I.classList.contains("json-toggle")){const C=I.dataset.path||"";o.value.has(C)?o.value.delete(C):o.value.add(C)}},T=P=>{const C=P.target.dataset.path;C&&(a.value=C)},y=()=>{a.value=""};return $n(()=>{const P=document.querySelector(".json-formatted");P&&(P.addEventListener("click",V),P.addEventListener("mouseover",T),P.addEventListener("mouseout",y))}),(P,I)=>(w(),E("div",Wp,[i("div",Qp,[i("div",Yp,[i("button",{onClick:v,class:be(["tool-btn",{active:s.value}])},[I[3]||(I[3]=i("svg",{viewBox:"0 0 16 16",fill:"currentColor"},[i("path",{d:"M2 4h12M2 8h12M2 12h12",stroke:"currentColor","stroke-width":"1.5",fill:"none"})],-1)),Pe(" "+U(s.value?"压缩":"格式化"),1)],2),i("button",{onClick:g,class:"tool-btn"},[(w(),E("svg",Zp,[i("path",{d:n.value?"M8 3l5 5-1.5 1.5L8 6l-3.5 3.5L3 8l5-5z":"M3 8l5 5 5-5-1.5-1.5L8 10 4.5 6.5 3 8z"},null,8,Xp)])),Pe(" "+U(n.value?"折叠":"展开"),1)]),i("button",{onClick:x,class:be(["tool-btn",{success:l.value}])},[l.value?(w(),E("svg",th,I[5]||(I[5]=[i("path",{d:"M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"},null,-1)]))):(w(),E("svg",eh,I[4]||(I[4]=[i("path",{d:"M4 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V2Zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H6ZM2 5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h1v1H2Z"},null,-1)]))),Pe(" "+U(l.value?"已复制":"复制"),1)],2)]),i("div",sh,[s.value?(w(),E("div",nh,[I[7]||(I[7]=i("svg",{viewBox:"0 0 16 16",fill:"currentColor"},[i("path",{d:"M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"})],-1)),$e(i("input",{"onUpdate:modelValue":I[0]||(I[0]=C=>r.value=C),placeholder:"搜索键或值...",onKeydown:I[1]||(I[1]=cl(C=>r.value="",["esc"])),class:"search-input"},null,544),[[qe,r.value]]),r.value?(w(),E("button",{key:0,onClick:I[2]||(I[2]=C=>r.value=""),class:"clear-search"},I[6]||(I[6]=[i("svg",{viewBox:"0 0 16 16",fill:"currentColor"},[i("path",{d:"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"})],-1)]))):le("",!0)])):le("",!0)]),i("div",oh,[a.value?(w(),E("span",rh,U(a.value),1)):le("",!0),i("span",ih,U(L()),1),s.value?(w(),E("span",lh,U(J()),1)):le("",!0)])]),i("div",ah,[s.value?(w(),E("div",{key:1,class:"json-formatted",innerHTML:f.value},null,8,uh)):(w(),E("div",ch,U(JSON.stringify(P.data)),1))],512)]))}}),bs=At(dh,[["__scopeId","data-v-6b3d677c"]]),fh={class:"log-detail-page"},ph={class:"top-nav"},hh={class:"nav-title"},vh={class:"content-wrapper"},gh={key:0,class:"loading-container"},mh={key:1,class:"detail-layout"},yh={class:"info-sidebar"},bh={class:"info-card"},_h={class:"info-list"},wh={class:"info-item"},kh={class:"call-id"},xh={class:"info-item"},Ch={class:"operation-badge"},$h={class:"info-item"},Sh={class:"model-info"},Th={class:"provider-icon-wrapper"},Eh=["src","alt"],Ah={class:"model-details"},Mh={class:"model-name"},Oh={class:"provider-name"},Ph={class:"info-item"},Rh={class:"time-value"},Lh={class:"info-item"},Ih={key:0,class:"info-card"},Nh={class:"params-grid"},jh={class:"param-item"},Bh={class:"param-value"},Uh={class:"param-item"},Hh={class:"param-value"},Dh={class:"param-item"},Vh={class:"param-item"},Fh={class:"content-area"},qh={class:"content-tabs"},Kh=["onClick"],zh={class:"tab-content"},Gh={class:"tab-label"},Jh={key:0,class:"tab-indicator"},Wh={class:"content-display"},Qh={key:0,class:"content-block"},Yh={class:"content-header"},Zh={class:"content-body"},Xh={key:1,class:"text-content"},ev={key:1,class:"content-block"},tv={class:"content-header"},sv={class:"content-body"},nv={key:1,class:"text-content"},ov={key:2,class:"content-block"},rv={class:"content-header"},iv={class:"content-body"},lv={key:1,class:"text-content"},av={key:3,class:"content-block"},cv={class:"content-header"},uv={class:"content-body"},dv={key:1,class:"text-content"},fv={key:4,class:"content-block error"},pv={class:"content-header"},hv={class:"content-body"},vv={key:1,class:"error-content"},gv={key:5,class:"empty-state"},mv=at({__name:"LogDetailModal",props:{log:{}},emits:["goBack"],setup(e,{emit:t}){const s=e,n=t,o=Z(null),r=Z(!1),l=Z("input"),a=T=>{if(typeof T=="object")return!0;if(typeof T=="string")try{return JSON.parse(T),!0}catch{return!1}return!1},c=T=>{if(typeof T=="object")return T;if(typeof T=="string")try{return JSON.parse(T)}catch{return T}return T},d=ve(()=>o.value?[{key:"input",label:"输入",hasContent:!!o.value.input},{key:"prompt",label:"提示词",hasContent:!!o.value.prompt},{key:"rawResponse",label:"原始响应",hasContent:!!o.value.rawResponse},{key:"output",label:"输出",hasContent:!!o.value.output},{key:"error",label:"错误",hasContent:!!o.value.errorMessage}]:[]);as(d,T=>{const y=T.find(P=>P.hasContent);y&&!T.find(P=>P.key===l.value&&P.hasContent)&&(l.value=y.key)},{immediate:!0});const u=ve(()=>{const T=d.value.find(y=>y.key===l.value);return(T==null?void 0:T.hasContent)||!1}),f=async()=>{var T;if((T=s.log)!=null&&T.callId)try{r.value=!0,o.value=await uo.getFullLog(s.log.callId)}catch(y){console.error("获取日志详情失败:",y),alert("获取日志详情失败,请稍后重试")}finally{r.value=!1}},v=()=>{n("goBack")},g=async T=>{try{await navigator.clipboard.writeText(T),alert("已复制到剪贴板")}catch(y){console.error("复制失败:",y),alert("复制失败,请手动复制")}},x=T=>new Date(T).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}),L=T=>T<1e3?`${T}ms`:`${(T/1e3).toFixed(2)}s`,J=T=>T<2e3?"fast":T<1e4?"normal":"slow",j=T=>T==="SUCCESS"?"success":"failed",V=T=>T==="SUCCESS"?"成功":"失败";return Dt(()=>{f()}),(T,y)=>{var P,I;return w(),E("div",fh,[i("div",ph,[i("button",{onClick:v,class:"nav-back"},y[5]||(y[5]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 19l-7-7 7-7"})],-1),Pe(" 返回日志 ")])),i("div",hh,[y[7]||(y[7]=i("h1",null,"调用详情",-1)),i("div",{class:be(["status-badge",j((P=o.value)==null?void 0:P.status)])},[y[6]||(y[6]=i("div",{class:"status-icon"},null,-1)),Pe(" "+U(V((I=o.value)==null?void 0:I.status)),1)],2)])]),i("div",vh,[r.value?(w(),E("div",gh,y[8]||(y[8]=[i("div",{class:"spinner-container"},[i("div",{class:"spinner"}),i("div",{class:"spinner-glow"})],-1),i("span",{class:"loading-text"},"加载详情中...",-1)]))):o.value?(w(),E("div",mh,[i("div",yh,[i("div",bh,[y[15]||(y[15]=i("div",{class:"card-title"},[i("div",{class:"title-icon"},"📊"),Pe(" 基本信息 ")],-1)),i("div",_h,[i("div",wh,[y[9]||(y[9]=i("span",{class:"label"},"调用ID",-1)),i("code",kh,U(o.value.callId),1)]),i("div",xh,[y[10]||(y[10]=i("span",{class:"label"},"操作类型",-1)),i("span",Ch,U(o.value.operationType),1)]),i("div",$h,[y[11]||(y[11]=i("span",{class:"label"},"模型",-1)),i("div",Sh,[i("div",Th,[i("img",{src:Ee(cs)(Ee(Rs)(o.value.modelName)),class:"provider-icon",alt:Ee(Qt)(Ee(Rs)(o.value.modelName))},null,8,Eh)]),i("div",Ah,[i("div",Mh,U(o.value.modelName),1),i("div",Oh,U(Ee(Qt)(Ee(Rs)(o.value.modelName))),1)])])]),i("div",Ph,[y[12]||(y[12]=i("span",{class:"label"},"调用时间",-1)),i("span",Rh,U(x(o.value.callTime)),1)]),i("div",Lh,[y[14]||(y[14]=i("span",{class:"label"},"耗时",-1)),i("span",{class:be(["duration-badge",J(o.value.duration)])},[y[13]||(y[13]=i("div",{class:"duration-icon"},null,-1)),Pe(" "+U(L(o.value.duration)),1)],2)])])]),o.value.requestParams?(w(),E("div",Ih,[y[22]||(y[22]=i("div",{class:"card-title"},[i("div",{class:"title-icon"},"⚙️"),Pe(" 请求参数 ")],-1)),i("div",Nh,[i("div",jh,[y[16]||(y[16]=i("div",{class:"param-label"},"MaxTokens",-1)),i("div",Bh,U(o.value.requestParams.maxTokens||"-"),1)]),i("div",Uh,[y[17]||(y[17]=i("div",{class:"param-label"},"Temperature",-1)),i("div",Hh,U(o.value.requestParams.temperature||"-"),1)]),i("div",Dh,[y[19]||(y[19]=i("div",{class:"param-label"},"JSON输出",-1)),i("div",{class:be(["param-toggle",o.value.requestParams.jsonOutput?"enabled":"disabled"])},[y[18]||(y[18]=i("div",{class:"toggle-indicator"},null,-1)),Pe(" "+U(o.value.requestParams.jsonOutput?"启用":"禁用"),1)],2)]),i("div",Vh,[y[21]||(y[21]=i("div",{class:"param-label"},"思考模式",-1)),i("div",{class:be(["param-toggle",o.value.requestParams.thinking?"enabled":"disabled"])},[y[20]||(y[20]=i("div",{class:"toggle-indicator"},null,-1)),Pe(" "+U(o.value.requestParams.thinking?"启用":"禁用"),1)],2)])])])):le("",!0)]),i("div",Fh,[i("div",qh,[(w(!0),E(ye,null,Le(d.value,C=>(w(),E("button",{key:C.key,onClick:$=>l.value=C.key,class:be(["tab-btn",{active:l.value===C.key}])},[i("div",zh,[i("span",Gh,U(C.label),1),C.hasContent?(w(),E("div",Jh,y[23]||(y[23]=[i("div",{class:"indicator-pulse"},null,-1)]))):le("",!0)])],10,Kh))),128))]),i("div",Wh,[l.value==="input"&&o.value.input?(w(),E("div",Qh,[i("div",Yh,[y[25]||(y[25]=i("div",{class:"header-left"},[i("div",{class:"content-icon"},"📥"),i("h3",null,"输入内容")],-1)),i("button",{onClick:y[0]||(y[0]=C=>g(JSON.stringify(o.value.input,null,2))),class:"copy-btn"},y[24]||(y[24]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),i("path",{d:"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"})],-1),i("span",null,"复制",-1)]))]),i("div",Zh,[a(o.value.input)?(w(),Ze(bs,{key:0,data:c(o.value.input),"max-height":"500px"},null,8,["data"])):(w(),E("pre",Xh,U(o.value.input),1))])])):le("",!0),l.value==="prompt"&&o.value.prompt?(w(),E("div",ev,[i("div",tv,[y[27]||(y[27]=i("div",{class:"header-left"},[i("div",{class:"content-icon"},"💭"),i("h3",null,"提示词")],-1)),i("button",{onClick:y[1]||(y[1]=C=>g(o.value.prompt)),class:"copy-btn"},y[26]||(y[26]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),i("path",{d:"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"})],-1),i("span",null,"复制",-1)]))]),i("div",sv,[a(o.value.prompt)?(w(),Ze(bs,{key:0,data:c(o.value.prompt),"max-height":"500px"},null,8,["data"])):(w(),E("pre",nv,U(o.value.prompt),1))])])):le("",!0),l.value==="rawResponse"&&o.value.rawResponse?(w(),E("div",ov,[i("div",rv,[y[29]||(y[29]=i("div",{class:"header-left"},[i("div",{class:"content-icon"},"🔄"),i("h3",null,"原始响应")],-1)),i("button",{onClick:y[2]||(y[2]=C=>g(o.value.rawResponse)),class:"copy-btn"},y[28]||(y[28]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),i("path",{d:"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"})],-1),i("span",null,"复制",-1)]))]),i("div",iv,[a(o.value.rawResponse)?(w(),Ze(bs,{key:0,data:c(o.value.rawResponse),"max-height":"500px"},null,8,["data"])):(w(),E("pre",lv,U(o.value.rawResponse),1))])])):le("",!0),l.value==="output"&&o.value.output?(w(),E("div",av,[i("div",cv,[y[31]||(y[31]=i("div",{class:"header-left"},[i("div",{class:"content-icon"},"📤"),i("h3",null,"输出内容")],-1)),i("button",{onClick:y[3]||(y[3]=C=>g(JSON.stringify(o.value.output,null,2))),class:"copy-btn"},y[30]||(y[30]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),i("path",{d:"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"})],-1),i("span",null,"复制",-1)]))]),i("div",uv,[a(o.value.output)?(w(),Ze(bs,{key:0,data:c(o.value.output),"max-height":"500px"},null,8,["data"])):(w(),E("pre",dv,U(o.value.output),1))])])):le("",!0),l.value==="error"&&o.value.errorMessage?(w(),E("div",fv,[i("div",pv,[y[33]||(y[33]=i("div",{class:"header-left"},[i("div",{class:"content-icon error-icon"},"⚠️"),i("h3",null,"错误信息")],-1)),i("button",{onClick:y[4]||(y[4]=C=>g(o.value.errorMessage)),class:"copy-btn"},y[32]||(y[32]=[i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor"},[i("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),i("path",{d:"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"})],-1),i("span",null,"复制",-1)]))]),i("div",hv,[a(o.value.errorMessage)?(w(),Ze(bs,{key:0,data:c(o.value.errorMessage),"max-height":"500px"},null,8,["data"])):(w(),E("div",vv,U(o.value.errorMessage),1))])])):le("",!0),u.value?le("",!0):(w(),E("div",gv,y[34]||(y[34]=[i("div",{class:"empty-illustration"},[i("div",{class:"empty-circle"}),i("div",{class:"empty-icon"},"📄")],-1),i("p",{class:"empty-text"},"该标签页暂无内容",-1)])))])])])):le("",!0)])])}}}),yv=At(mv,[["__scopeId","data-v-7246130a"]]),bv={class:"ai-log-content"},_v={key:1},wv={class:"content-header"},kv={class:"header-actions"},xv=["disabled"],Cv={key:0,class:"w-4 h-4 animate-spin",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},$v=["disabled"],Sv={class:"main-content"},Tv={key:0,class:"loading-state"},Ev={key:1,class:"empty-state"},Av={key:2,class:"logs-list"},Mv={class:"list-header"},Ov={class:"header-info"},Pv={class:"log-count"},Rv={class:"search-box"},Lv={class:"filter-controls"},Iv=["value"],Nv=["value"],jv={class:"table-container"},Bv={class:"table-body"},Uv={class:"cell time-cell"},Hv={class:"time-info"},Dv={class:"time-relative"},Vv={class:"time-full"},Fv={class:"cell status-cell"},qv={class:"cell operation-cell"},Kv={class:"operation-tag"},zv={class:"cell model-cell"},Gv={class:"model-info"},Jv={class:"model-avatar"},Wv=["src"],Qv={class:"model-details"},Yv={class:"model-name"},Zv={class:"provider-name"},Xv={class:"cell duration-cell"},e1={class:"cell actions-cell"},t1=["onClick"],s1={key:0,class:"pagination"},n1=["disabled"],o1={class:"page-info"},r1=["disabled"],Kn=20,i1=at({__name:"AICallLogViewer",setup(e){const t=Z(!1),s=Z([]),n=Z(""),o=Z(""),r=Z(""),l=Z(""),a=Z(1),c=Z(!1),d=Z(null),u=ve(()=>[...new Set(s.value.map(C=>C.operationType))]),f=ve(()=>[...new Set(s.value.map(C=>C.modelName))]),v=ve(()=>{let C=s.value;if(n.value){const $=n.value.toLowerCase();C=C.filter(O=>{var W;return O.callId.toLowerCase().includes($)||O.operationType.toLowerCase().includes($)||O.modelName.toLowerCase().includes($)||((W=O.errorMessage)==null?void 0:W.toLowerCase().includes($))})}return o.value&&(C=C.filter($=>$.operationType===o.value)),r.value&&(C=C.filter($=>$.modelName===r.value)),l.value&&(C=C.filter($=>$.status===l.value)),C.sort(($,O)=>new Date(O.callTime).getTime()-new Date($.callTime).getTime())}),g=ve(()=>Math.ceil(v.value.length/Kn)),x=ve(()=>{const C=(a.value-1)*Kn,$=C+Kn;return v.value.slice(C,$)}),L=C=>{const $=Date.now(),O=new Date(C).getTime(),W=$-O,te=Math.floor(W/6e4),k=Math.floor(W/36e5),_=Math.floor(W/864e5);return _>0?`${_}天前`:k>0?`${k}小时前`:te>0?`${te}分钟前`:"刚刚"},J=C=>new Date(C).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit",second:"2-digit"}),j=C=>!C&&C!==0?"0ms":C<1e3?`${C}ms`:`${(C/1e3).toFixed(2)}s`,V=C=>!C&&C!==0?"duration-unknown":C<2e3?"duration-fast":C<1e4?"duration-normal":"duration-slow",T=async()=>{try{t.value=!0;const C=await uo.getAllLogSummaries();s.value=C}catch(C){console.error("加载日志失败:",C),alert("加载日志失败,请稍后重试")}finally{t.value=!1}},y=async()=>{if(confirm("确定要清空所有日志吗?此操作不可恢复。"))try{t.value=!0,await uo.clearLogs(),await T(),alert("日志已清空")}catch(C){console.error("清空日志失败:",C),alert("清空日志失败,请稍后重试")}finally{t.value=!1}},P=C=>{d.value=C,c.value=!0},I=()=>{c.value=!1,d.value=null,T()};return Dt(()=>{T()}),(C,$)=>(w(),E("div",bv,[c.value?(w(),Ze(yv,{key:0,log:d.value,onGoBack:I},null,8,["log"])):(w(),E("div",_v,[i("div",wv,[$[8]||($[8]=i("h2",null,"AI调用日志",-1)),i("div",kv,[i("button",{onClick:T,class:"btn btn-secondary",disabled:t.value},[t.value?(w(),E("svg",Cv,$[6]||($[6]=[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},null,-1)]))):le("",!0),i("span",null,U(t.value?"加载中":"刷新"),1)],8,xv),i("button",{onClick:y,class:"btn btn-danger",disabled:t.value||s.value.length===0},$[7]||($[7]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"})],-1),i("span",null,"清空",-1)]),8,$v)])]),i("div",Sv,[t.value&&s.value.length===0?(w(),E("div",Tv,$[9]||($[9]=[i("div",{class:"loading-spinner"},null,-1),i("p",null,"正在加载调用日志...",-1)]))):s.value.length===0?(w(),E("div",Ev,$[10]||($[10]=[i("div",{class:"empty-icon"},"📋",-1),i("h3",null,"暂无调用日志",-1),i("p",null,"当AI模型被调用时,相关日志将在这里显示",-1)]))):(w(),E("div",Av,[i("div",Mv,[i("div",Ov,[i("span",Pv,"共 "+U(v.value.length)+" 条记录",1),i("div",Rv,[$[11]||($[11]=i("svg",{class:"search-icon",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})],-1)),$e(i("input",{"onUpdate:modelValue":$[0]||($[0]=O=>n.value=O),type:"text",placeholder:"搜索日志...",class:"search-input"},null,512),[[qe,n.value]])])]),i("div",Lv,[$e(i("select",{"onUpdate:modelValue":$[1]||($[1]=O=>o.value=O),class:"filter-select"},[$[12]||($[12]=i("option",{value:""},"全部操作",-1)),(w(!0),E(ye,null,Le(u.value,O=>(w(),E("option",{key:O,value:O},U(O),9,Iv))),128))],512),[[vt,o.value]]),$e(i("select",{"onUpdate:modelValue":$[2]||($[2]=O=>r.value=O),class:"filter-select"},[$[13]||($[13]=i("option",{value:""},"全部模型",-1)),(w(!0),E(ye,null,Le(f.value,O=>(w(),E("option",{key:O,value:O},U(O),9,Nv))),128))],512),[[vt,r.value]]),$e(i("select",{"onUpdate:modelValue":$[3]||($[3]=O=>l.value=O),class:"filter-select"},$[14]||($[14]=[i("option",{value:""},"全部状态",-1),i("option",{value:"SUCCESS"},"成功",-1),i("option",{value:"FAILED"},"失败",-1)]),512),[[vt,l.value]])])]),i("div",jv,[$[17]||($[17]=Oo('
时间
状态
操作
模型
耗时
详情
',1)),i("div",Bv,[(w(!0),E(ye,null,Le(x.value,O=>(w(),E("div",{key:O.callId,class:be(["table-row",{"row-failed":O.status!=="SUCCESS"}])},[i("div",Uv,[i("div",Hv,[i("span",Dv,U(L(O.callTime)),1),i("span",Vv,U(J(O.callTime)),1)])]),i("div",Fv,[i("span",{class:be(["status-indicator",O.status.toLowerCase()])},[$[15]||($[15]=i("span",{class:"status-dot"},null,-1)),Pe(" "+U(O.status==="SUCCESS"?"成功":"失败"),1)],2)]),i("div",qv,[i("span",Kv,U(O.operationType),1)]),i("div",zv,[i("div",Gv,[i("div",Jv,[i("img",{src:Ee(cs)(Ee(Rs)(O.modelName)),alt:"provider",class:"provider-icon"},null,8,Wv)]),i("div",Qv,[i("div",Yv,U(O.modelName),1),i("div",Zv,U(Ee(Qt)(Ee(Rs)(O.modelName))),1)])])]),i("div",Xv,[i("span",{class:be(["duration-value",V(O.duration)])},U(j(O.duration)),3)]),i("div",e1,[i("button",{onClick:W=>P(O),class:"action-btn",title:"查看详情"},$[16]||($[16]=[i("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"}),i("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"})],-1)]),8,t1)])],2))),128))])]),g.value>1?(w(),E("div",s1,[i("button",{onClick:$[4]||($[4]=O=>a.value=Math.max(1,a.value-1)),disabled:a.value===1,class:"page-btn"}," 上一页 ",8,n1),i("span",o1," 第 "+U(a.value)+" 页,共 "+U(g.value)+" 页 ",1),i("button",{onClick:$[5]||($[5]=O=>a.value=Math.min(g.value,a.value+1)),disabled:a.value===g.value,class:"page-btn"}," 下一页 ",8,r1)])):le("",!0)]))])]))]))}}),l1=At(i1,[["__scopeId","data-v-584cc492"]]),a1={async getSystemOverview(){return Oe(`${Me.BASE_URL}/sf-chain/system/overview`,{method:"GET",requireAuth:!0})},async createBackup(){return Oe(`${Me.BASE_URL}/sf-chain/system/backup`,{method:"POST",requireAuth:!0})},async refreshSystem(){return Oe(`${Me.BASE_URL}/sf-chain/system/refresh`,{method:"POST",requireAuth:!0})},async resetSystem(){return Oe(`${Me.BASE_URL}/sf-chain/system/reset`,{method:"POST",requireAuth:!0})}},c1={class:"api-config"},u1={class:"main-content"},d1={class:"sidebar"},f1={class:"tab-navigation"},p1={class:"tab-list"},h1=["onClick"],v1={class:"tab-icon"},g1=["innerHTML"],m1={class:"tab-content"},y1={class:"tab-title"},b1={class:"tab-description"},_1={class:"status-card"},w1={class:"status-content"},k1={class:"status-item"},x1={class:"status-value"},C1={class:"stats-card"},$1={class:"stats-grid"},S1={class:"stat-item"},T1={class:"stat-value"},E1={class:"stat-item"},A1={class:"stat-value"},M1={class:"stat-item"},O1={class:"stat-value"},P1={class:"content-area"},R1=at({__name:"App",setup(e){const t=[{key:"api",title:"AI模型",description:"配置AI模型API",icon:` + + + + + + + `},{key:"operations",title:"AI节点",description:"管理AI节点映射",icon:` + + + + + + + + + + + + + + + `},{key:"logs",title:"AI日志",description:"查看AI调用日志",icon:` + + + + + + + + `}],s=Z("api"),n=Z({totalModels:0,enabledModels:0,configuredOperations:0,totalOperations:0,enabledOperations:0,lastUpdate:Date.now()}),o=c=>{s.value=c},r=c=>c?new Date(c).toLocaleString():"未知",l=async()=>{try{const c=await a1.getSystemOverview();n.value=c}catch(c){const d=c instanceof Error?c.message:"获取系统概览失败";console.error("Failed to fetch system overview:",d)}},a=c=>{n.value={...n.value,...c}};return Dt(()=>{Lo()&&l()}),(c,d)=>(w(),E("div",c1,[Be(Ru,{"on-refresh":l}),i("div",u1,[i("div",d1,[i("div",f1,[d[1]||(d[1]=i("div",{class:"tab-header"},[i("h3",null,"配置导航")],-1)),i("div",p1,[(w(),E(ye,null,Le(t,u=>i("div",{key:u.key,class:be(["tab-item",{active:s.value===u.key}]),onClick:f=>o(u.key)},[i("div",v1,[i("div",{class:"icon-svg",innerHTML:u.icon},null,8,g1)]),i("div",m1,[i("div",y1,U(u.title),1),i("div",b1,U(u.description),1)]),d[0]||(d[0]=i("div",{class:"tab-indicator"},null,-1))],10,h1)),64))])]),i("div",_1,[d[4]||(d[4]=i("div",{class:"status-header"},[i("span",{class:"status-icon"},"📊"),i("span",{class:"status-title"},"系统状态")],-1)),i("div",w1,[d[3]||(d[3]=i("div",{class:"status-item"},[i("span",{class:"status-label"},"运行状态"),i("span",{class:"status-value running"},"正常运行")],-1)),i("div",k1,[d[2]||(d[2]=i("span",{class:"status-label"},"最后更新",-1)),i("span",x1,U(r(n.value.lastUpdate)),1)])])]),i("div",C1,[d[8]||(d[8]=i("div",{class:"stats-header"},[i("span",{class:"stats-icon"},"📈"),i("span",{class:"stats-title"},"统计信息")],-1)),i("div",$1,[i("div",S1,[i("span",T1,U(n.value.totalModels||0),1),d[5]||(d[5]=i("span",{class:"stat-label"},"总模型",-1))]),i("div",E1,[i("span",A1,U(n.value.enabledModels||0),1),d[6]||(d[6]=i("span",{class:"stat-label"},"已启用",-1))]),i("div",M1,[i("span",O1,U(n.value.configuredOperations||0),1),d[7]||(d[7]=i("span",{class:"stat-label"},"已配置",-1))])])])]),d[9]||(d[9]=i("div",{class:"divider"},null,-1)),i("div",P1,[s.value==="api"?(w(),Ze(Xd,{key:0,"system-overview":n.value,onUpdateOverview:a},null,8,["system-overview"])):le("",!0),s.value==="operations"?(w(),Ze(Pp,{key:1,"system-overview":n.value,onUpdateOverview:a},null,8,["system-overview"])):le("",!0),s.value==="logs"?(w(),Ze(l1,{key:2,"system-overview":n.value,onUpdateOverview:a},null,8,["system-overview"])):le("",!0),s.value==="system"?(w(),Ze(Jp,{key:3,"system-overview":n.value,onUpdateOverview:a},null,8,["system-overview"])):le("",!0)])])]))}}),fl=At(R1,[["__scopeId","data-v-6f5fc07f"]]);/*! + * vue-router v4.5.1 + * (c) 2025 Eduardo San Martin Morote + * @license MIT + */const ss=typeof document<"u";function pl(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function L1(e){return e.__esModule||e[Symbol.toStringTag]==="Module"||e.default&&pl(e.default)}const pe=Object.assign;function zn(e,t){const s={};for(const n in t){const o=t[n];s[n]=lt(o)?o.map(e):e(o)}return s}const Ls=()=>{},lt=Array.isArray,hl=/#/g,I1=/&/g,N1=/\//g,j1=/=/g,B1=/\?/g,vl=/\+/g,U1=/%5B/g,H1=/%5D/g,gl=/%5E/g,D1=/%60/g,ml=/%7B/g,V1=/%7C/g,yl=/%7D/g,F1=/%20/g;function Io(e){return encodeURI(""+e).replace(V1,"|").replace(U1,"[").replace(H1,"]")}function q1(e){return Io(e).replace(ml,"{").replace(yl,"}").replace(gl,"^")}function fo(e){return Io(e).replace(vl,"%2B").replace(F1,"+").replace(hl,"%23").replace(I1,"%26").replace(D1,"`").replace(ml,"{").replace(yl,"}").replace(gl,"^")}function K1(e){return fo(e).replace(j1,"%3D")}function z1(e){return Io(e).replace(hl,"%23").replace(B1,"%3F")}function G1(e){return e==null?"":z1(e).replace(N1,"%2F")}function qs(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const J1=/\/$/,W1=e=>e.replace(J1,"");function Gn(e,t,s="/"){let n,o={},r="",l="";const a=t.indexOf("#");let c=t.indexOf("?");return a=0&&(c=-1),c>-1&&(n=t.slice(0,c),r=t.slice(c+1,a>-1?a:t.length),o=e(r)),a>-1&&(n=n||t.slice(0,a),l=t.slice(a,t.length)),n=X1(n??t,s),{fullPath:n+(r&&"?")+r+l,path:n,query:o,hash:qs(l)}}function Q1(e,t){const s=t.query?e(t.query):"";return t.path+(s&&"?")+s+(t.hash||"")}function Er(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Y1(e,t,s){const n=t.matched.length-1,o=s.matched.length-1;return n>-1&&n===o&&ds(t.matched[n],s.matched[o])&&bl(t.params,s.params)&&e(t.query)===e(s.query)&&t.hash===s.hash}function ds(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function bl(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const s in e)if(!Z1(e[s],t[s]))return!1;return!0}function Z1(e,t){return lt(e)?Ar(e,t):lt(t)?Ar(t,e):e===t}function Ar(e,t){return lt(t)?e.length===t.length&&e.every((s,n)=>s===t[n]):e.length===1&&e[0]===t}function X1(e,t){if(e.startsWith("/"))return e;if(!e)return t;const s=t.split("/"),n=e.split("/"),o=n[n.length-1];(o===".."||o===".")&&n.push("");let r=s.length-1,l,a;for(l=0;l1&&r--;else break;return s.slice(0,r).join("/")+"/"+n.slice(l).join("/")}const Ot={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var Ks;(function(e){e.pop="pop",e.push="push"})(Ks||(Ks={}));var Is;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Is||(Is={}));function eg(e){if(!e)if(ss){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),W1(e)}const tg=/^[^#]+#/;function sg(e,t){return e.replace(tg,"#")+t}function ng(e,t){const s=document.documentElement.getBoundingClientRect(),n=e.getBoundingClientRect();return{behavior:t.behavior,left:n.left-s.left-(t.left||0),top:n.top-s.top-(t.top||0)}}const Pn=()=>({left:window.scrollX,top:window.scrollY});function og(e){let t;if("el"in e){const s=e.el,n=typeof s=="string"&&s.startsWith("#"),o=typeof s=="string"?n?document.getElementById(s.slice(1)):document.querySelector(s):s;if(!o)return;t=ng(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function Mr(e,t){return(history.state?history.state.position-t:-1)+e}const po=new Map;function rg(e,t){po.set(e,t)}function ig(e){const t=po.get(e);return po.delete(e),t}let lg=()=>location.protocol+"//"+location.host;function _l(e,t){const{pathname:s,search:n,hash:o}=t,r=e.indexOf("#");if(r>-1){let a=o.includes(e.slice(r))?e.slice(r).length:1,c=o.slice(a);return c[0]!=="/"&&(c="/"+c),Er(c,"")}return Er(s,e)+n+o}function ag(e,t,s,n){let o=[],r=[],l=null;const a=({state:v})=>{const g=_l(e,location),x=s.value,L=t.value;let J=0;if(v){if(s.value=g,t.value=v,l&&l===x){l=null;return}J=L?v.position-L.position:0}else n(g);o.forEach(j=>{j(s.value,x,{delta:J,type:Ks.pop,direction:J?J>0?Is.forward:Is.back:Is.unknown})})};function c(){l=s.value}function d(v){o.push(v);const g=()=>{const x=o.indexOf(v);x>-1&&o.splice(x,1)};return r.push(g),g}function u(){const{history:v}=window;v.state&&v.replaceState(pe({},v.state,{scroll:Pn()}),"")}function f(){for(const v of r)v();r=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:c,listen:d,destroy:f}}function Or(e,t,s,n=!1,o=!1){return{back:e,current:t,forward:s,replaced:n,position:window.history.length,scroll:o?Pn():null}}function cg(e){const{history:t,location:s}=window,n={value:_l(e,s)},o={value:t.state};o.value||r(n.value,{back:null,current:n.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function r(c,d,u){const f=e.indexOf("#"),v=f>-1?(s.host&&document.querySelector("base")?e:e.slice(f))+c:lg()+e+c;try{t[u?"replaceState":"pushState"](d,"",v),o.value=d}catch(g){console.error(g),s[u?"replace":"assign"](v)}}function l(c,d){const u=pe({},t.state,Or(o.value.back,c,o.value.forward,!0),d,{position:o.value.position});r(c,u,!0),n.value=c}function a(c,d){const u=pe({},o.value,t.state,{forward:c,scroll:Pn()});r(u.current,u,!0);const f=pe({},Or(n.value,c,null),{position:u.position+1},d);r(c,f,!1),n.value=c}return{location:n,state:o,push:a,replace:l}}function ug(e){e=eg(e);const t=cg(e),s=ag(e,t.state,t.location,t.replace);function n(r,l=!0){l||s.pauseListeners(),history.go(r)}const o=pe({location:"",base:e,go:n,createHref:sg.bind(null,e)},t,s);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function dg(e){return typeof e=="string"||e&&typeof e=="object"}function wl(e){return typeof e=="string"||typeof e=="symbol"}const kl=Symbol("");var Pr;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Pr||(Pr={}));function fs(e,t){return pe(new Error,{type:e,[kl]:!0},t)}function _t(e,t){return e instanceof Error&&kl in e&&(t==null||!!(e.type&t))}const Rr="[^/]+?",fg={sensitive:!1,strict:!1,start:!0,end:!0},pg=/[.+*?^${}()[\]/\\]/g;function hg(e,t){const s=pe({},fg,t),n=[];let o=s.start?"^":"";const r=[];for(const d of e){const u=d.length?[]:[90];s.strict&&!d.length&&(o+="/");for(let f=0;ft.length?t.length===1&&t[0]===80?1:-1:0}function xl(e,t){let s=0;const n=e.score,o=t.score;for(;s0&&t[t.length-1]<0}const gg={type:0,value:""},mg=/[a-zA-Z0-9_]/;function yg(e){if(!e)return[[]];if(e==="/")return[[gg]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(g){throw new Error(`ERR (${s})/"${d}": ${g}`)}let s=0,n=s;const o=[];let r;function l(){r&&o.push(r),r=[]}let a=0,c,d="",u="";function f(){d&&(s===0?r.push({type:0,value:d}):s===1||s===2||s===3?(r.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${d}) must be alone in its segment. eg: '/:ids+.`),r.push({type:1,value:d,regexp:u,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),d="")}function v(){d+=c}for(;a{l(T)}:Ls}function l(f){if(wl(f)){const v=n.get(f);v&&(n.delete(f),s.splice(s.indexOf(v),1),v.children.forEach(l),v.alias.forEach(l))}else{const v=s.indexOf(f);v>-1&&(s.splice(v,1),f.record.name&&n.delete(f.record.name),f.children.forEach(l),f.alias.forEach(l))}}function a(){return s}function c(f){const v=xg(f,s);s.splice(v,0,f),f.record.name&&!jr(f)&&n.set(f.record.name,f)}function d(f,v){let g,x={},L,J;if("name"in f&&f.name){if(g=n.get(f.name),!g)throw fs(1,{location:f});J=g.record.name,x=pe(Ir(v.params,g.keys.filter(T=>!T.optional).concat(g.parent?g.parent.keys.filter(T=>T.optional):[]).map(T=>T.name)),f.params&&Ir(f.params,g.keys.map(T=>T.name))),L=g.stringify(x)}else if(f.path!=null)L=f.path,g=s.find(T=>T.re.test(L)),g&&(x=g.parse(L),J=g.record.name);else{if(g=v.name?n.get(v.name):s.find(T=>T.re.test(v.path)),!g)throw fs(1,{location:f,currentLocation:v});J=g.record.name,x=pe({},v.params,f.params),L=g.stringify(x)}const j=[];let V=g;for(;V;)j.unshift(V.record),V=V.parent;return{name:J,path:L,params:x,matched:j,meta:kg(j)}}e.forEach(f=>r(f));function u(){s.length=0,n.clear()}return{addRoute:r,resolve:d,removeRoute:l,clearRoutes:u,getRoutes:a,getRecordMatcher:o}}function Ir(e,t){const s={};for(const n of t)n in e&&(s[n]=e[n]);return s}function Nr(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:wg(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function wg(e){const t={},s=e.props||!1;if("component"in e)t.default=s;else for(const n in e.components)t[n]=typeof s=="object"?s[n]:s;return t}function jr(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function kg(e){return e.reduce((t,s)=>pe(t,s.meta),{})}function Br(e,t){const s={};for(const n in e)s[n]=n in t?t[n]:e[n];return s}function xg(e,t){let s=0,n=t.length;for(;s!==n;){const r=s+n>>1;xl(e,t[r])<0?n=r:s=r+1}const o=Cg(e);return o&&(n=t.lastIndexOf(o,n-1)),n}function Cg(e){let t=e;for(;t=t.parent;)if(Cl(t)&&xl(e,t)===0)return t}function Cl({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function $g(e){const t={};if(e===""||e==="?")return t;const n=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;or&&fo(r)):[n&&fo(n)]).forEach(r=>{r!==void 0&&(t+=(t.length?"&":"")+s,r!=null&&(t+="="+r))})}return t}function Sg(e){const t={};for(const s in e){const n=e[s];n!==void 0&&(t[s]=lt(n)?n.map(o=>o==null?null:""+o):n==null?n:""+n)}return t}const Tg=Symbol(""),Hr=Symbol(""),No=Symbol(""),$l=Symbol(""),ho=Symbol("");function _s(){let e=[];function t(n){return e.push(n),()=>{const o=e.indexOf(n);o>-1&&e.splice(o,1)}}function s(){e=[]}return{add:t,list:()=>e.slice(),reset:s}}function It(e,t,s,n,o,r=l=>l()){const l=n&&(n.enterCallbacks[o]=n.enterCallbacks[o]||[]);return()=>new Promise((a,c)=>{const d=v=>{v===!1?c(fs(4,{from:s,to:t})):v instanceof Error?c(v):dg(v)?c(fs(2,{from:t,to:v})):(l&&n.enterCallbacks[o]===l&&typeof v=="function"&&l.push(v),a())},u=r(()=>e.call(n&&n.instances[o],t,s,d));let f=Promise.resolve(u);e.length<3&&(f=f.then(d)),f.catch(v=>c(v))})}function Jn(e,t,s,n,o=r=>r()){const r=[];for(const l of e)for(const a in l.components){let c=l.components[a];if(!(t!=="beforeRouteEnter"&&!l.instances[a]))if(pl(c)){const u=(c.__vccOpts||c)[t];u&&r.push(It(u,s,n,l,a,o))}else{let d=c();r.push(()=>d.then(u=>{if(!u)throw new Error(`Couldn't resolve component "${a}" at "${l.path}"`);const f=L1(u)?u.default:u;l.mods[a]=u,l.components[a]=f;const g=(f.__vccOpts||f)[t];return g&&It(g,s,n,l,a,o)()}))}}return r}function Dr(e){const t=$t(No),s=$t($l),n=ve(()=>{const c=Ee(e.to);return t.resolve(c)}),o=ve(()=>{const{matched:c}=n.value,{length:d}=c,u=c[d-1],f=s.matched;if(!u||!f.length)return-1;const v=f.findIndex(ds.bind(null,u));if(v>-1)return v;const g=Vr(c[d-2]);return d>1&&Vr(u)===g&&f[f.length-1].path!==g?f.findIndex(ds.bind(null,c[d-2])):v}),r=ve(()=>o.value>-1&&Pg(s.params,n.value.params)),l=ve(()=>o.value>-1&&o.value===s.matched.length-1&&bl(s.params,n.value.params));function a(c={}){if(Og(c)){const d=t[Ee(e.replace)?"replace":"push"](Ee(e.to)).catch(Ls);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>d),d}return Promise.resolve()}return{route:n,href:ve(()=>n.value.href),isActive:r,isExactActive:l,navigate:a}}function Eg(e){return e.length===1?e[0]:e}const Ag=at({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:Dr,setup(e,{slots:t}){const s=hs(Dr(e)),{options:n}=$t(No),o=ve(()=>({[Fr(e.activeClass,n.linkActiveClass,"router-link-active")]:s.isActive,[Fr(e.exactActiveClass,n.linkExactActiveClass,"router-link-exact-active")]:s.isExactActive}));return()=>{const r=t.default&&Eg(t.default(s));return e.custom?r:Ro("a",{"aria-current":s.isExactActive?e.ariaCurrentValue:null,href:s.href,onClick:s.navigate,class:o.value},r)}}}),Mg=Ag;function Og(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Pg(e,t){for(const s in t){const n=t[s],o=e[s];if(typeof n=="string"){if(n!==o)return!1}else if(!lt(o)||o.length!==n.length||n.some((r,l)=>r!==o[l]))return!1}return!0}function Vr(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Fr=(e,t,s)=>e??t??s,Rg=at({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:s}){const n=$t(ho),o=ve(()=>e.route||n.value),r=$t(Hr,0),l=ve(()=>{let d=Ee(r);const{matched:u}=o.value;let f;for(;(f=u[d])&&!f.components;)d++;return d}),a=ve(()=>o.value.matched[l.value]);on(Hr,ve(()=>l.value+1)),on(Tg,a),on(ho,o);const c=Z();return as(()=>[c.value,a.value,e.name],([d,u,f],[v,g,x])=>{u&&(u.instances[f]=d,g&&g!==u&&d&&d===v&&(u.leaveGuards.size||(u.leaveGuards=g.leaveGuards),u.updateGuards.size||(u.updateGuards=g.updateGuards))),d&&u&&(!g||!ds(u,g)||!v)&&(u.enterCallbacks[f]||[]).forEach(L=>L(d))},{flush:"post"}),()=>{const d=o.value,u=e.name,f=a.value,v=f&&f.components[u];if(!v)return qr(s.default,{Component:v,route:d});const g=f.props[u],x=g?g===!0?d.params:typeof g=="function"?g(d):g:null,J=Ro(v,pe({},x,t,{onVnodeUnmounted:j=>{j.component.isUnmounted&&(f.instances[u]=null)},ref:c}));return qr(s.default,{Component:J,route:d})||J}}});function qr(e,t){if(!e)return null;const s=e(t);return s.length===1?s[0]:s}const Lg=Rg;function Ig(e){const t=_g(e.routes,e),s=e.parseQuery||$g,n=e.stringifyQuery||Ur,o=e.history,r=_s(),l=_s(),a=_s(),c=la(Ot);let d=Ot;ss&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=zn.bind(null,S=>""+S),f=zn.bind(null,G1),v=zn.bind(null,qs);function g(S,z){let q,Q;return wl(S)?(q=t.getRecordMatcher(S),Q=z):Q=S,t.addRoute(Q,q)}function x(S){const z=t.getRecordMatcher(S);z&&t.removeRoute(z)}function L(){return t.getRoutes().map(S=>S.record)}function J(S){return!!t.getRecordMatcher(S)}function j(S,z){if(z=pe({},z||c.value),typeof S=="string"){const m=Gn(s,S,z.path),A=t.resolve({path:m.path},z),R=o.createHref(m.fullPath);return pe(m,A,{params:v(A.params),hash:qs(m.hash),redirectedFrom:void 0,href:R})}let q;if(S.path!=null)q=pe({},S,{path:Gn(s,S.path,z.path).path});else{const m=pe({},S.params);for(const A in m)m[A]==null&&delete m[A];q=pe({},S,{params:f(m)}),z.params=f(z.params)}const Q=t.resolve(q,z),_e=S.hash||"";Q.params=u(v(Q.params));const p=Q1(n,pe({},S,{hash:q1(_e),path:Q.path})),h=o.createHref(p);return pe({fullPath:p,hash:_e,query:n===Ur?Sg(S.query):S.query||{}},Q,{redirectedFrom:void 0,href:h})}function V(S){return typeof S=="string"?Gn(s,S,c.value.path):pe({},S)}function T(S,z){if(d!==S)return fs(8,{from:z,to:S})}function y(S){return C(S)}function P(S){return y(pe(V(S),{replace:!0}))}function I(S){const z=S.matched[S.matched.length-1];if(z&&z.redirect){const{redirect:q}=z;let Q=typeof q=="function"?q(S):q;return typeof Q=="string"&&(Q=Q.includes("?")||Q.includes("#")?Q=V(Q):{path:Q},Q.params={}),pe({query:S.query,hash:S.hash,params:Q.path!=null?{}:S.params},Q)}}function C(S,z){const q=d=j(S),Q=c.value,_e=S.state,p=S.force,h=S.replace===!0,m=I(q);if(m)return C(pe(V(m),{state:typeof m=="object"?pe({},_e,m.state):_e,force:p,replace:h}),z||q);const A=q;A.redirectedFrom=z;let R;return!p&&Y1(n,Q,q)&&(R=fs(16,{to:A,from:Q}),b(Q,Q,!0,!1)),(R?Promise.resolve(R):W(A,Q)).catch(M=>_t(M)?_t(M,2)?M:G(M):ce(M,A,Q)).then(M=>{if(M){if(_t(M,2))return C(pe({replace:h},V(M.to),{state:typeof M.to=="object"?pe({},_e,M.to.state):_e,force:p}),z||A)}else M=k(A,Q,!0,h,_e);return te(A,Q,M),M})}function $(S,z){const q=T(S,z);return q?Promise.reject(q):Promise.resolve()}function O(S){const z=me.values().next().value;return z&&typeof z.runWithContext=="function"?z.runWithContext(S):S()}function W(S,z){let q;const[Q,_e,p]=Ng(S,z);q=Jn(Q.reverse(),"beforeRouteLeave",S,z);for(const m of Q)m.leaveGuards.forEach(A=>{q.push(It(A,S,z))});const h=$.bind(null,S,z);return q.push(h),He(q).then(()=>{q=[];for(const m of r.list())q.push(It(m,S,z));return q.push(h),He(q)}).then(()=>{q=Jn(_e,"beforeRouteUpdate",S,z);for(const m of _e)m.updateGuards.forEach(A=>{q.push(It(A,S,z))});return q.push(h),He(q)}).then(()=>{q=[];for(const m of p)if(m.beforeEnter)if(lt(m.beforeEnter))for(const A of m.beforeEnter)q.push(It(A,S,z));else q.push(It(m.beforeEnter,S,z));return q.push(h),He(q)}).then(()=>(S.matched.forEach(m=>m.enterCallbacks={}),q=Jn(p,"beforeRouteEnter",S,z,O),q.push(h),He(q))).then(()=>{q=[];for(const m of l.list())q.push(It(m,S,z));return q.push(h),He(q)}).catch(m=>_t(m,8)?m:Promise.reject(m))}function te(S,z,q){a.list().forEach(Q=>O(()=>Q(S,z,q)))}function k(S,z,q,Q,_e){const p=T(S,z);if(p)return p;const h=z===Ot,m=ss?history.state:{};q&&(Q||h?o.replace(S.fullPath,pe({scroll:h&&m&&m.scroll},_e)):o.push(S.fullPath,_e)),c.value=S,b(S,z,q,h),G()}let _;function B(){_||(_=o.listen((S,z,q)=>{if(!Se.listening)return;const Q=j(S),_e=I(Q);if(_e){C(pe(_e,{replace:!0,force:!0}),Q).catch(Ls);return}d=Q;const p=c.value;ss&&rg(Mr(p.fullPath,q.delta),Pn()),W(Q,p).catch(h=>_t(h,12)?h:_t(h,2)?(C(pe(V(h.to),{force:!0}),Q).then(m=>{_t(m,20)&&!q.delta&&q.type===Ks.pop&&o.go(-1,!1)}).catch(Ls),Promise.reject()):(q.delta&&o.go(-q.delta,!1),ce(h,Q,p))).then(h=>{h=h||k(Q,p,!1),h&&(q.delta&&!_t(h,8)?o.go(-q.delta,!1):q.type===Ks.pop&&_t(h,20)&&o.go(-1,!1)),te(Q,p,h)}).catch(Ls)}))}let ne=_s(),oe=_s(),ae;function ce(S,z,q){G(S);const Q=oe.list();return Q.length?Q.forEach(_e=>_e(S,z,q)):console.error(S),Promise.reject(S)}function Ae(){return ae&&c.value!==Ot?Promise.resolve():new Promise((S,z)=>{ne.add([S,z])})}function G(S){return ae||(ae=!S,B(),ne.list().forEach(([z,q])=>S?q(S):z()),ne.reset()),S}function b(S,z,q,Q){const{scrollBehavior:_e}=e;if(!ss||!_e)return Promise.resolve();const p=!q&&ig(Mr(S.fullPath,0))||(Q||!q)&&history.state&&history.state.scroll||null;return $n().then(()=>_e(S,z,p)).then(h=>h&&og(h)).catch(h=>ce(h,S,z))}const ue=S=>o.go(S);let Y;const me=new Set,Se={currentRoute:c,listening:!0,addRoute:g,removeRoute:x,clearRoutes:t.clearRoutes,hasRoute:J,getRoutes:L,resolve:j,options:e,push:y,replace:P,go:ue,back:()=>ue(-1),forward:()=>ue(1),beforeEach:r.add,beforeResolve:l.add,afterEach:a.add,onError:oe.add,isReady:Ae,install(S){const z=this;S.component("RouterLink",Mg),S.component("RouterView",Lg),S.config.globalProperties.$router=z,Object.defineProperty(S.config.globalProperties,"$route",{enumerable:!0,get:()=>Ee(c)}),ss&&!Y&&c.value===Ot&&(Y=!0,y(o.location).catch(_e=>{}));const q={};for(const _e in Ot)Object.defineProperty(q,_e,{get:()=>c.value[_e],enumerable:!0});S.provide(No,z),S.provide($l,fi(q)),S.provide(ho,c);const Q=S.unmount;me.add(S),S.unmount=function(){me.delete(S),me.size<1&&(d=Ot,_&&_(),_=null,c.value=Ot,Y=!1,ae=!1),Q()}}};function He(S){return S.reduce((z,q)=>z.then(()=>O(q)),Promise.resolve())}return Se}function Ng(e,t){const s=[],n=[],o=[],r=Math.max(t.matched.length,e.matched.length);for(let l=0;lds(d,a))?n.push(a):s.push(a));const c=e.matched[l];c&&(t.matched.find(d=>ds(d,c))||o.push(c))}return[s,n,o]}const jg=Ig({history:ug("/"),routes:[{path:"/",name:"home",component:fl}]}),yn=ul(fl);yn.use(ou());yn.use(jg);wu.initialize().then(()=>{yn.mount("#app")}).catch(e=>{console.error("Failed to initialize API config:",e),yn.mount("#app")}); diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-DtzThp8m.css b/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-DtzThp8m.css new file mode 100644 index 0000000..9edc15b --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/assets/index-DtzThp8m.css @@ -0,0 +1 @@ +:root{--vt-c-white: #ffffff;--vt-c-white-soft: #f8f8f8;--vt-c-white-mute: #f2f2f2;--vt-c-black: #181818;--vt-c-black-soft: #222222;--vt-c-black-mute: #282828;--vt-c-indigo: #2c3e50;--vt-c-divider-light-1: rgba(60, 60, 60, .29);--vt-c-divider-light-2: rgba(60, 60, 60, .12);--vt-c-divider-dark-1: rgba(84, 84, 84, .65);--vt-c-divider-dark-2: rgba(84, 84, 84, .48);--vt-c-text-light-1: var(--vt-c-indigo);--vt-c-text-light-2: rgba(60, 60, 60, .66);--vt-c-text-dark-1: var(--vt-c-white);--vt-c-text-dark-2: rgba(235, 235, 235, .64)}:root{--color-background: var(--vt-c-white);--color-background-soft: var(--vt-c-white-soft);--color-background-mute: var(--vt-c-white-mute);--color-border: var(--vt-c-divider-light-2);--color-border-hover: var(--vt-c-divider-light-1);--color-heading: var(--vt-c-text-light-1);--color-text: var(--vt-c-text-light-1);--section-gap: 160px}@media (prefers-color-scheme: dark){:root{--color-background: var(--vt-c-black);--color-background-soft: var(--vt-c-black-soft);--color-background-mute: var(--vt-c-black-mute);--color-border: var(--vt-c-divider-dark-2);--color-border-hover: var(--vt-c-divider-dark-1);--color-heading: var(--vt-c-text-dark-1);--color-text: var(--vt-c-text-dark-2)}}*,*:before,*:after{box-sizing:border-box;margin:0;font-weight:400}body{min-height:100vh;color:var(--color-text);background:var(--color-background);transition:color .5s,background-color .5s;line-height:1.6;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:15px;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{box-sizing:border-box}body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#fafafa}#app{min-height:100vh;width:100%}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.container{max-width:1400px;margin:0 auto;padding:0 20px}.text-center{text-align:center}.mt-4{margin-top:1rem}.mb-4{margin-bottom:1rem}.p-4{padding:1rem}a{text-decoration:none;color:#667eea;transition:.3s}a:hover{color:#764ba2}@media (min-width: 1024px){#app{width:100%;max-width:none}}.toast-overlay[data-v-4c886fb0]{display:flex;align-items:center;justify-content:center;padding:0;pointer-events:none}.toast-container[data-v-4c886fb0]{min-width:320px;max-width:480px;width:auto;background:#fffffffa;border-radius:16px;box-shadow:0 25px 50px -12px #00000026,0 10px 20px -8px #0000001a,0 0 0 1px #fffc;backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);overflow:hidden;pointer-events:auto;border:1px solid rgba(255,255,255,.3);transform:translateZ(0)}.toast-content[data-v-4c886fb0]{display:flex;align-items:flex-start;padding:20px;gap:14px}.toast-icon-wrapper[data-v-4c886fb0]{flex-shrink:0;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden}.toast-icon-wrapper[data-v-4c886fb0]:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;opacity:.12;background:currentColor;transform:scale(0);animation:iconPulse-4c886fb0 .6s cubic-bezier(.34,1.56,.64,1) forwards}@keyframes iconPulse-4c886fb0{to{transform:scale(1)}}.toast-icon[data-v-4c886fb0]{position:relative;z-index:1;transform:scale(0);animation:iconScale-4c886fb0 .5s cubic-bezier(.34,1.56,.64,1) .1s forwards}@keyframes iconScale-4c886fb0{to{transform:scale(1)}}.toast-message[data-v-4c886fb0]{flex:1;min-width:0;padding-top:2px}.toast-title[data-v-4c886fb0]{font-size:15px;font-weight:600;margin-bottom:4px;line-height:1.4;color:#1a1a1a;opacity:0;transform:translateY(8px);animation:slideInUp-4c886fb0 .4s cubic-bezier(.4,0,.2,1) .2s forwards}.toast-text[data-v-4c886fb0]{font-size:14px;line-height:1.5;color:#666;opacity:0;transform:translateY(8px);animation:slideInUp-4c886fb0 .4s cubic-bezier(.4,0,.2,1) .3s forwards}@keyframes slideInUp-4c886fb0{to{opacity:1;transform:translateY(0)}}.toast-close[data-v-4c886fb0]{flex-shrink:0;width:28px;height:28px;border:none;background:#0000000a;cursor:pointer;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#999;transition:all .25s cubic-bezier(.4,0,.2,1);margin-top:8px;opacity:0;transform:scale(.8);animation:fadeInScale-4c886fb0 .3s cubic-bezier(.4,0,.2,1) .4s forwards}@keyframes fadeInScale-4c886fb0{to{opacity:1;transform:scale(1)}}.toast-close[data-v-4c886fb0]:hover{background:#00000014;color:#666;transform:scale(1.05)}.toast-close[data-v-4c886fb0]:active{transform:scale(.95)}.toast-progress[data-v-4c886fb0]{height:3px;background:#0000000a;overflow:hidden}.toast-progress-bar[data-v-4c886fb0]{height:100%;width:100%;transform-origin:left;animation:progressShrink-4c886fb0 linear}@keyframes progressShrink-4c886fb0{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.toast-success[data-v-4c886fb0]{background:linear-gradient(135deg,#10b98108,#34d39908);border:1px solid rgba(16,185,129,.15)}.toast-success .toast-icon-wrapper[data-v-4c886fb0]{color:#10b981}.toast-success .toast-title[data-v-4c886fb0]{color:#065f46}.toast-success .toast-progress-bar[data-v-4c886fb0]{background:linear-gradient(90deg,#10b981,#34d399)}.toast-error[data-v-4c886fb0]{background:linear-gradient(135deg,#ef444408,#f8717108);border:1px solid rgba(239,68,68,.15)}.toast-error .toast-icon-wrapper[data-v-4c886fb0]{color:#ef4444}.toast-error .toast-title[data-v-4c886fb0]{color:#7f1d1d}.toast-error .toast-progress-bar[data-v-4c886fb0]{background:linear-gradient(90deg,#ef4444,#f87171)}.toast-warning[data-v-4c886fb0]{background:linear-gradient(135deg,#f59e0b08,#fbbf2408);border:1px solid rgba(245,158,11,.15)}.toast-warning .toast-icon-wrapper[data-v-4c886fb0]{color:#f59e0b}.toast-warning .toast-title[data-v-4c886fb0]{color:#78350f}.toast-warning .toast-progress-bar[data-v-4c886fb0]{background:linear-gradient(90deg,#f59e0b,#fbbf24)}.toast-info[data-v-4c886fb0]{background:linear-gradient(135deg,#3b82f608,#60a5fa08);border:1px solid rgba(59,130,246,.15)}.toast-info .toast-icon-wrapper[data-v-4c886fb0]{color:#3b82f6}.toast-info .toast-title[data-v-4c886fb0]{color:#1e3a8a}.toast-info .toast-progress-bar[data-v-4c886fb0]{background:linear-gradient(90deg,#3b82f6,#60a5fa)}.toast-enter-active[data-v-4c886fb0]{transition:all .5s cubic-bezier(.34,1.56,.64,1)}.toast-leave-active[data-v-4c886fb0]{transition:all .35s cubic-bezier(.4,0,1,1)}.toast-enter-from[data-v-4c886fb0]{opacity:0;transform:translate(-50%) scale(.85) translateY(-30px);filter:blur(4px)}.toast-leave-to[data-v-4c886fb0]{opacity:0;transform:translate(-50%) scale(.95) translateY(-15px);filter:blur(2px)}@media (max-width: 640px){.toast-container[data-v-4c886fb0]{min-width:auto;max-width:calc(100vw - 32px);margin:0 16px}.toast-content[data-v-4c886fb0]{padding:18px;gap:12px}.toast-icon-wrapper[data-v-4c886fb0]{width:40px;height:40px}.toast-title[data-v-4c886fb0]{font-size:14px}.toast-text[data-v-4c886fb0]{font-size:13px}}@media (prefers-color-scheme: dark){.toast-container[data-v-4c886fb0]{background:#1e1e1efa;border:1px solid rgba(255,255,255,.08)}.toast-title[data-v-4c886fb0]{color:#f5f5f5}.toast-text[data-v-4c886fb0]{color:#a3a3a3}.toast-close[data-v-4c886fb0]{background:#ffffff14;color:#a3a3a3}.toast-close[data-v-4c886fb0]:hover{background:#ffffff26;color:#f5f5f5}}.header-bar[data-v-677538a9]{background:linear-gradient(135deg,#fffffffa,#f8fafcf2);-webkit-backdrop-filter:blur(24px) saturate(200%);backdrop-filter:blur(24px) saturate(200%);border-radius:16px;padding:1.25rem 2rem;margin-bottom:1.5rem;box-shadow:0 8px 32px #667eea14,0 4px 16px #0000000a,inset 0 1px #fffc;border:1px solid rgba(102,126,234,.1);position:relative;overflow:hidden;height:96px}.header-bar[data-v-677538a9]:before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,#667eea,#764ba2,#f093fb,#4facfe,#00f2fe);opacity:.9}.header-content[data-v-677538a9]{display:flex;align-items:center;justify-content:space-between;gap:2rem;height:100%}.header-left[data-v-677538a9]{flex:0 0 auto}.brand-section[data-v-677538a9]{display:flex;align-items:center;gap:1rem}.brand-logo[data-v-677538a9]{width:52px;height:52px;background:linear-gradient(135deg,#667eea1a,#764ba21a,#f093fb1a);border-radius:12px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 20px #667eea33,inset 0 1px #fff6;border:1px solid rgba(102,126,234,.2);position:relative;transition:all .4s cubic-bezier(.4,0,.2,1)}.brand-logo[data-v-677538a9]:hover{transform:translateY(-1px) scale(1.02);box-shadow:0 8px 32px #667eea4d,inset 0 1px #ffffff80}.logo-svg[data-v-677538a9]{width:36px;height:36px;transition:all .4s ease}.brand-logo:hover .logo-svg[data-v-677538a9]{transform:scale(1.05) rotate(3deg)}.brand-text[data-v-677538a9]{display:flex;flex-direction:column;gap:.125rem}.brand-title[data-v-677538a9]{font-size:1.875rem;font-weight:700;background:linear-gradient(135deg,#1e293b,#667eea,#764ba2);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin:0;letter-spacing:-.025em;line-height:1.1}.brand-subtitle[data-v-677538a9]{font-size:.8rem;color:#64748b;font-weight:500;margin:0;letter-spacing:.02em;opacity:.8}.header-right[data-v-677538a9]{flex:1;display:flex;justify-content:flex-end}.auth-section[data-v-677538a9]{display:flex;align-items:center;gap:1.5rem}.connection-status[data-v-677538a9]{display:flex;align-items:center;gap:.625rem;padding:.625rem 1rem;background:#ef44440f;border:1px solid rgba(239,68,68,.12);border-radius:12px;transition:all .3s ease;position:relative;overflow:hidden}.connection-status.connected[data-v-677538a9]{background:#10b9810f;border-color:#10b9811f}.status-indicator[data-v-677538a9]{position:relative;width:10px;height:10px}.status-pulse[data-v-677538a9]{position:absolute;width:100%;height:100%;border-radius:50%;background:#ef4444;animation:pulse-677538a9 2s infinite}.connection-status.connected .status-pulse[data-v-677538a9]{background:#10b981}@keyframes pulse-677538a9{0%{transform:scale(.8);opacity:1}50%{transform:scale(1.2);opacity:.6}to{transform:scale(.8);opacity:1}}.status-label[data-v-677538a9]{font-size:.8rem;font-weight:600;color:#ef4444;transition:color .3s ease}.connection-status.connected .status-label[data-v-677538a9]{color:#10b981}.auth-controls[data-v-677538a9]{display:flex;align-items:center}.token-input-group[data-v-677538a9]{display:flex;align-items:center;background:#fffffff2;border:1.5px solid rgba(226,232,240,.5);border-radius:16px;padding:.375rem;transition:all .3s ease;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 2px 12px #0000000a}.token-input-group[data-v-677538a9]:focus-within{border-color:#6366f1;box-shadow:0 0 0 3px #6366f114,0 4px 20px #0000000f;transform:translateY(-1px)}.token-input[data-v-677538a9]{flex:1;min-width:200px;padding:.75rem 1rem;border:none;background:transparent;font-size:.8rem;color:#1e293b;outline:none;font-weight:500;letter-spacing:.02em}.token-input[data-v-677538a9]::placeholder{color:#94a3b8;font-weight:400}.input-actions[data-v-677538a9]{display:flex;gap:.375rem}.action-btn[data-v-677538a9]{width:36px;height:36px;border:none;border-radius:10px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.action-btn svg[data-v-677538a9]{width:16px;height:16px;transition:all .3s ease}.save-btn[data-v-677538a9]{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;box-shadow:0 2px 12px #6366f140}.save-btn[data-v-677538a9]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 20px #6366f159}.save-btn[data-v-677538a9]:disabled{background:#e2e8f0;color:#94a3b8;cursor:not-allowed;transform:none;box-shadow:none}.refresh-btn[data-v-677538a9]{background:linear-gradient(135deg,#10b981,#06b6d4);color:#fff;box-shadow:0 2px 12px #10b98140}.refresh-btn[data-v-677538a9]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 20px #10b98159}.refresh-btn:hover:not(:disabled) svg[data-v-677538a9]{transform:rotate(180deg)}.refresh-btn[data-v-677538a9]:disabled{background:#e2e8f0;color:#94a3b8;cursor:not-allowed;transform:none;box-shadow:none}@media (max-width: 1200px){.header-content[data-v-677538a9]{flex-direction:column;gap:1.5rem}.header-bar[data-v-677538a9]{height:auto;padding:1.25rem 1.5rem}.header-right[data-v-677538a9]{justify-content:center}.auth-section[data-v-677538a9]{flex-direction:column;gap:1rem}.token-input-group[data-v-677538a9]{width:100%;max-width:360px}}@media (max-width: 768px){.header-bar[data-v-677538a9]{padding:1rem 1.25rem}.brand-title[data-v-677538a9]{font-size:1.5rem}.brand-logo[data-v-677538a9]{width:40px;height:40px}.logo-svg[data-v-677538a9]{width:28px;height:28px}.token-input[data-v-677538a9]{min-width:160px}.auth-section[data-v-677538a9]{width:100%}.token-input-group[data-v-677538a9]{max-width:none}}.content-header[data-v-48fd4b43]{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1rem}.header-left[data-v-48fd4b43]{flex:1}.header-left h2[data-v-48fd4b43]{font-size:1.5rem;font-weight:600;color:#1a202c;margin:0 0 .125rem}.header-left p[data-v-48fd4b43]{font-size:.8125rem;color:#718096;margin:0}.header-actions[data-v-48fd4b43]{display:flex;gap:.75rem;align-items:center}.stats-section[data-v-48fd4b43]{display:flex;gap:.75rem;margin-bottom:1rem;flex-wrap:wrap}.stat-card[data-v-48fd4b43]{background:#fff;padding:.75rem 1rem;border-radius:8px;box-shadow:0 1px 3px #0000001a;border:2px solid #e2e8f0;min-width:90px;display:flex;justify-content:space-between;align-items:center;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none}.stat-card[data-v-48fd4b43]:hover{border-color:#667eea;transform:translateY(-1px);box-shadow:0 4px 12px #667eea26}.stat-card.active[data-v-48fd4b43]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-color:#667eea}.stat-content[data-v-48fd4b43]{flex:1}.stat-number[data-v-48fd4b43]{font-size:1.25rem;font-weight:700;margin-bottom:.125rem;line-height:1}.stat-label[data-v-48fd4b43]{font-size:.6875rem;opacity:.8;font-weight:500}.stat-icon[data-v-48fd4b43]{font-size:1.25rem;opacity:.7;margin-left:.5rem;display:flex;align-items:center;justify-content:center}.stat-provider-icon[data-v-48fd4b43]{width:20px;height:20px;object-fit:contain}.main-content[data-v-48fd4b43]{background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000001a;border:1px solid #e2e8f0}.list-header[data-v-48fd4b43]{padding:1rem;border-bottom:1px solid #e2e8f0;background:#f8fafc}.header-info[data-v-48fd4b43]{display:flex;justify-content:space-between;align-items:center}.header-info h3[data-v-48fd4b43]{font-size:1rem;font-weight:600;color:#1a202c;margin:0}.search-box[data-v-48fd4b43]{position:relative;width:250px}.search-icon[data-v-48fd4b43]{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);width:.875rem;height:.875rem;color:#9ca3af}.search-input[data-v-48fd4b43]{width:100%;padding:.5rem 2.5rem .5rem 2rem;border:1px solid #e5e7eb;border-radius:6px;font-size:.8125rem;background:#fff}.search-input[data-v-48fd4b43]:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 2px #667eea1a}.clear-search[data-v-48fd4b43]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#9ca3af;padding:.25rem;border-radius:4px;transition:all .2s ease}.clear-search[data-v-48fd4b43]:hover{background:#f3f4f6;color:#374151}.table-header[data-v-48fd4b43]{display:grid;grid-template-columns:2.6fr 1.5fr 1fr 2.2fr .8fr 1.2fr;gap:.75rem;padding:.75rem 1rem;background:#f1f5f9;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#475569;text-transform:uppercase;letter-spacing:.025em}.header-cell[data-v-48fd4b43]{display:flex;align-items:center}.models-container[data-v-48fd4b43]{max-height:55vh;overflow-y:auto}.model-row[data-v-48fd4b43]{display:grid;grid-template-columns:2.6fr 1.5fr 1fr 2.2fr .8fr 1.2fr;gap:.75rem;padding:.75rem 1rem;border-bottom:1px solid #f1f5f9;transition:background-color .2s ease;align-items:center}.model-row[data-v-48fd4b43]:hover{background:#f8fafc}.model-row.disabled[data-v-48fd4b43]{opacity:.6}.model-row[data-v-48fd4b43]:last-child{border-bottom:none}.model-cell[data-v-48fd4b43]{display:flex;align-items:center}.model-identity[data-v-48fd4b43]{display:flex;align-items:center;gap:.75rem;width:100%}.model-avatar[data-v-48fd4b43]{width:32px;height:32px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;cursor:pointer;transition:all .2s ease;padding:4px}.model-avatar[data-v-48fd4b43]:hover{background:#0000000d;transform:scale(1.05)}.provider-icon[data-v-48fd4b43]{width:100%;height:100%;object-fit:contain}.model-info[data-v-48fd4b43]{flex:1;min-width:0}.model-name[data-v-48fd4b43]{font-size:.875rem;font-weight:600;color:#1a202c;margin:0 0 .25rem;cursor:pointer;transition:color .2s ease;word-break:break-all}.model-name[data-v-48fd4b43]:hover{color:#667eea}.provider-badge[data-v-48fd4b43]{padding:.125rem .5rem;border-radius:10px;font-size:.625rem;font-weight:600;background:#e2e8f0;color:#4a5568}.provider-badge.openai[data-v-48fd4b43]{background:#dcfce7;color:#166534}.provider-badge.anthropic[data-v-48fd4b43]{background:#fef3c7;color:#92400e}.provider-badge.google[data-v-48fd4b43]{background:#dbeafe;color:#1e40af}.provider-badge.deepseek[data-v-48fd4b43]{background:#e0e7ff;color:#3730a3}.provider-badge.doubao[data-v-48fd4b43]{background:#fce7f3;color:#be185d}.provider-badge.qianwen[data-v-48fd4b43]{background:#c6e0e9;color:#0f0e0e}.base-url-cell[data-v-48fd4b43]{overflow:hidden;display:flex;align-items:center}.base-url-text[data-v-48fd4b43]{font-size:.8125rem;color:#374151;cursor:pointer;transition:color .2s ease;word-break:break-all;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.base-url-text[data-v-48fd4b43]:hover{color:#667eea}.params-cell[data-v-48fd4b43]{display:flex;align-items:center;justify-content:center}.params-text[data-v-48fd4b43]{font-size:.8125rem;color:#374151;font-weight:500;text-align:center}.description-cell[data-v-48fd4b43]{overflow:hidden;display:flex;align-items:center}.description-text[data-v-48fd4b43]{font-size:.8125rem;color:#6b7280;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.status-cell[data-v-48fd4b43]{display:flex;align-items:center;justify-content:center}.status-badge[data-v-48fd4b43]{padding:.25rem .5rem;border-radius:12px;font-size:.6875rem;font-weight:600;display:inline-block}.status-badge.enabled[data-v-48fd4b43]{background:#dcfce7;color:#166534}.status-badge.disabled[data-v-48fd4b43]{background:#fecaca;color:#991b1b}.actions-cell[data-v-48fd4b43]{display:flex;justify-content:center;align-items:center}.action-buttons[data-v-48fd4b43]{display:flex;gap:.25rem}.action-btn[data-v-48fd4b43]{width:32px;height:32px;border:none;border-radius:6px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;position:relative}.action-btn[data-v-48fd4b43]:disabled{opacity:.6;cursor:not-allowed}.action-btn.test[data-v-48fd4b43]{background:#dcfce7;color:#166534}.action-btn.test[data-v-48fd4b43]:hover:not(:disabled){background:#bbf7d0;transform:translateY(-1px);box-shadow:0 2px 8px #22c55e4d}.action-btn.clone[data-v-48fd4b43]{background:linear-gradient(135deg,#fff9c4,#fef3bd);color:#6b7280;border:1px solid #f3e8ff}.action-btn.clone[data-v-48fd4b43]:hover:not(:disabled){background:linear-gradient(135deg,#fef3bd,#fde68a);transform:translateY(-1px);box-shadow:0 4px 12px #fef3bd4d;border-color:#e5e7eb}.action-btn.edit[data-v-48fd4b43]{background:#dbeafe;color:#1e40af}.action-btn.edit[data-v-48fd4b43]:hover:not(:disabled){background:#bfdbfe;transform:translateY(-1px);box-shadow:0 2px 8px #3b82f64d}.action-btn.delete[data-v-48fd4b43]{background:#fecaca;color:#991b1b}.action-btn.delete[data-v-48fd4b43]:hover:not(:disabled){background:#fca5a5;transform:translateY(-1px);box-shadow:0 2px 8px #ef44444d}.loading-state[data-v-48fd4b43],.empty-state[data-v-48fd4b43]{text-align:center;padding:3rem 2rem;color:#6b7280}.loading-spinner[data-v-48fd4b43]{width:32px;height:32px;border:3px solid #e5e7eb;border-top:3px solid #667eea;border-radius:50%;animation:spin-48fd4b43 1s linear infinite;margin:0 auto 1rem}.empty-icon[data-v-48fd4b43]{font-size:3rem;margin-bottom:1rem;opacity:.5}.empty-state h3[data-v-48fd4b43]{font-size:1.125rem;font-weight:600;color:#374151;margin:0 0 .5rem}.empty-state p[data-v-48fd4b43]{font-size:.875rem;margin:0}.modal-overlay[data-v-48fd4b43]{position:fixed;top:0;left:0;right:0;bottom:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal-content[data-v-48fd4b43]{background:#fff;border-radius:12px;width:90%;max-width:800px;max-height:85vh;overflow:hidden;box-shadow:0 20px 40px #00000040;border:1px solid rgba(255,255,255,.2);display:flex;flex-direction:column}.modal-header[data-v-48fd4b43]{display:flex;justify-content:space-between;align-items:center;padding:.875rem 1.25rem;border-bottom:1px solid #e5e7eb;background:linear-gradient(135deg,#f8fafc,#f1f5f9);border-radius:12px 12px 0 0;flex-shrink:0}.modal-header h3[data-v-48fd4b43]{font-size:1.125rem;font-weight:600;color:#1a202c;margin:0}.btn-close[data-v-48fd4b43]{background:none;border:none;cursor:pointer;color:#6b7280;padding:.25rem;border-radius:4px;transition:all .2s ease}.btn-close[data-v-48fd4b43]:hover{background:#e5e7eb;color:#374151}.modal-body[data-v-48fd4b43]{padding:1.25rem;flex:1;overflow-y:auto}.form-grid[data-v-48fd4b43]{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;margin-bottom:1rem}.form-column[data-v-48fd4b43]{display:flex;flex-direction:column;gap:.875rem}.form-group[data-v-48fd4b43]{margin-bottom:0}.form-row[data-v-48fd4b43]{display:grid;grid-template-columns:1fr 1fr;gap:.75rem}.form-group label[data-v-48fd4b43]{display:block;font-weight:600;color:#374151;margin-bottom:.375rem;font-size:.75rem}.form-input[data-v-48fd4b43],.form-textarea[data-v-48fd4b43]{width:100%;padding:.5rem .75rem;border:1px solid #e5e7eb;border-radius:6px;font-size:.875rem;transition:all .2s ease;background:#fff}.form-input[data-v-48fd4b43]:focus,.form-textarea[data-v-48fd4b43]:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 2px #667eea1a}.form-textarea[data-v-48fd4b43]{resize:vertical;min-height:50px;font-family:inherit}.input-wrapper[data-v-48fd4b43]{position:relative}.toggle-visibility[data-v-48fd4b43]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:#6b7280;padding:.25rem;border-radius:4px;transition:all .2s ease}.toggle-visibility[data-v-48fd4b43]:hover{background:#f3f4f6;color:#374151}.form-actions[data-v-48fd4b43]{display:flex;gap:.75rem;justify-content:flex-end;margin-top:.75rem;padding-top:.75rem;border-top:1px solid #e5e7eb}.btn[data-v-48fd4b43]{padding:.5rem 1rem;border:none;border-radius:6px;font-weight:600;cursor:pointer;transition:all .2s ease;display:inline-flex;align-items:center;gap:.375rem;font-size:.75rem;min-width:70px;justify-content:center}.btn[data-v-48fd4b43]:disabled{opacity:.6;cursor:not-allowed}.btn-primary[data-v-48fd4b43]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.btn-primary[data-v-48fd4b43]:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 12px #667eea4d}.btn-secondary[data-v-48fd4b43]{background:#f3f4f6;color:#374151;border:1px solid #d1d5db}.btn-secondary[data-v-48fd4b43]:hover:not(:disabled){background:#e5e7eb}.btn-loading[data-v-48fd4b43]{width:12px;height:12px;border:2px solid transparent;border-top:2px solid currentColor;border-radius:50%;animation:spin-48fd4b43 1s linear infinite}.copy-toast[data-v-48fd4b43]{position:fixed;top:2rem;right:2rem;background:#059669;color:#fff;padding:.75rem 1rem;border-radius:8px;box-shadow:0 4px 12px #00000026;display:flex;align-items:center;gap:.5rem;font-size:.875rem;font-weight:500;z-index:1001;animation:slideIn-48fd4b43 .3s ease-out}@keyframes slideIn-48fd4b43{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}.w-4[data-v-48fd4b43]{width:1rem}.h-4[data-v-48fd4b43]{height:1rem}.w-5[data-v-48fd4b43]{width:1.25rem}.h-5[data-v-48fd4b43]{height:1.25rem}.animate-spin[data-v-48fd4b43]{animation:spin-48fd4b43 1s linear infinite}@keyframes spin-48fd4b43{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 1024px){.table-header[data-v-48fd4b43],.model-row[data-v-48fd4b43]{grid-template-columns:2fr 2.5fr 1fr 1.2fr .8fr 1fr;gap:.5rem}.search-box[data-v-48fd4b43]{width:200px}.modal-content[data-v-48fd4b43]{max-width:600px}}@media (max-width: 768px){.content-header[data-v-48fd4b43]{flex-direction:column;gap:1rem}.stats-section[data-v-48fd4b43]{grid-template-columns:repeat(2,1fr)}.header-info[data-v-48fd4b43]{flex-direction:column;gap:.75rem;align-items:flex-start}.search-box[data-v-48fd4b43]{width:100%}.table-header[data-v-48fd4b43]{display:none}.model-row[data-v-48fd4b43]{display:flex;flex-direction:column;gap:.75rem;padding:1rem;border:1px solid #e5e7eb;border-radius:8px;margin-bottom:.75rem}.models-container[data-v-48fd4b43]{padding:.75rem}.model-identity[data-v-48fd4b43]{width:100%}.action-buttons[data-v-48fd4b43]{justify-content:flex-end;width:100%}.form-row[data-v-48fd4b43]{grid-template-columns:1fr}.form-actions[data-v-48fd4b43]{flex-direction:column}.copy-toast[data-v-48fd4b43]{top:1rem;left:1rem;right:1rem}.modal-content[data-v-48fd4b43]{width:95%;max-width:none;margin:1rem;max-height:70vh}.modal-header[data-v-48fd4b43]{padding:.75rem 1rem}.modal-body[data-v-48fd4b43]{padding:.875rem 1rem}}@media (max-width: 480px){.stats-section[data-v-48fd4b43]{grid-template-columns:1fr}.stat-card[data-v-48fd4b43]{min-width:auto}.modal-content[data-v-48fd4b43]{max-height:75vh}}.ai-node-config-content[data-v-de75772f]{padding:0;min-height:100vh}.content-header[data-v-de75772f]{display:flex;justify-content:space-between;align-items:center;padding:14px 24px;background:#fffffff2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid rgba(226,232,240,.6);margin:0;box-shadow:0 1px 3px #0000000d}.header-left h2[data-v-de75772f]{margin:0;font-size:20px;font-weight:700;background:linear-gradient(135deg,#1e293b,#475569);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.header-right[data-v-de75772f]{display:flex;align-items:center;gap:20px}.header-stats[data-v-de75772f]{display:flex;gap:12px;align-items:center}.stat-item[data-v-de75772f]{display:flex;flex-direction:column;align-items:center;padding:8px 12px;background:#ffffffe6;border-radius:8px;border:1px solid rgba(226,232,240,.6);min-width:56px;box-shadow:0 1px 4px #0000000f;transition:all .3s ease}.stat-item[data-v-de75772f]:hover{transform:translateY(-1px);box-shadow:0 2px 8px #0000001a}.stat-item.success[data-v-de75772f]{background:linear-gradient(135deg,#f0fdf4,#dcfce7);border-color:#bbf7d0cc}.stat-item.warning[data-v-de75772f]{background:linear-gradient(135deg,#fffbeb,#fef3c7);border-color:#fed7aacc}.stat-item.info[data-v-de75772f]{background:linear-gradient(135deg,#eff6ff,#dbeafe);border-color:#bfdbfecc}.stat-number[data-v-de75772f]{font-size:16px;font-weight:800;color:#1e293b;line-height:1}.stat-label[data-v-de75772f]{font-size:10px;color:#64748b;margin-top:2px;text-align:center;font-weight:500}.header-actions[data-v-de75772f]{display:flex;gap:8px}.btn[data-v-de75772f]{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:8px;font-size:13px;font-weight:600;border:1px solid transparent;cursor:pointer;transition:all .3s ease;box-shadow:0 1px 4px #00000014;position:relative;overflow:hidden}.btn[data-v-de75772f]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s}.btn[data-v-de75772f]:hover:before{left:100%}.btn-secondary[data-v-de75772f]{background:linear-gradient(135deg,#f8fafc,#f1f5f9);color:#475569;border-color:#e2e8f0cc}.btn-secondary[data-v-de75772f]:hover{background:linear-gradient(135deg,#e2e8f0,#cbd5e1);transform:translateY(-1px);box-shadow:0 2px 8px #0000001f}.btn-primary[data-v-de75772f]{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-color:transparent}.btn-primary[data-v-de75772f]:hover{background:linear-gradient(135deg,#2563eb,#1d4ed8);transform:translateY(-1px);box-shadow:0 2px 12px #3b82f666}.btn[data-v-de75772f]:disabled{opacity:.5;cursor:not-allowed;transform:none}.toolbar[data-v-de75772f]{display:flex;justify-content:space-between;align-items:center;padding:12px 24px;background:#fffc;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid rgba(226,232,240,.4)}.search-container[data-v-de75772f]{position:relative;width:280px}.search-icon[data-v-de75772f]{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:16px;height:16px;color:#9ca3af;transition:color .3s ease}.search-input[data-v-de75772f]{width:100%;padding:8px 12px 8px 32px;border:1px solid rgba(209,213,219,.6);border-radius:8px;font-size:13px;background:#ffffffe6;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all .3s ease;box-shadow:0 1px 4px #0000000a}.search-input[data-v-de75772f]:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a,0 2px 8px #00000014}.search-input:focus+.search-icon[data-v-de75772f]{color:#3b82f6}.clear-btn[data-v-de75772f]{position:absolute;right:8px;top:50%;transform:translateY(-50%);padding:4px;background:none;border:none;color:#9ca3af;cursor:pointer;border-radius:4px;transition:all .3s ease}.clear-btn[data-v-de75772f]:hover{background:#9ca3af1a;color:#6b7280}.filter-tabs[data-v-de75772f]{display:flex;gap:6px;background:#fff9;padding:3px;border-radius:8px;border:1px solid rgba(226,232,240,.6)}.filter-tab[data-v-de75772f]{padding:6px 12px;border:none;background:transparent;border-radius:6px;font-size:12px;font-weight:500;cursor:pointer;transition:all .3s ease;color:#64748b}.filter-tab[data-v-de75772f]:hover{background:#3b82f61a;color:#3b82f6}.filter-tab.active[data-v-de75772f]{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;box-shadow:0 1px 4px #3b82f64d}.count[data-v-de75772f]{background:#ffffff40;padding:1px 6px;border-radius:8px;font-size:10px;margin-left:4px;font-weight:600}.main-content[data-v-de75772f]{padding:20px}.loading-state[data-v-de75772f],.empty-state[data-v-de75772f]{text-align:center;padding:60px 20px}.loading-spinner[data-v-de75772f]{width:36px;height:36px;border:3px solid rgba(59,130,246,.1);border-top:3px solid #3b82f6;border-radius:50%;animation:spin-de75772f 1s linear infinite;margin:0 auto 16px}@keyframes spin-de75772f{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.empty-icon[data-v-de75772f]{font-size:48px;margin-bottom:16px;opacity:.6}.operations-grid[data-v-de75772f]{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px}.operation-card[data-v-de75772f]{background:#fffffff2;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:12px;border:1px solid rgba(226,232,240,.6);padding:16px;transition:all .4s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 8px #0000000f;position:relative;overflow:hidden}.operation-card[data-v-de75772f]:before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,#e2e8f0,#cbd5e1);transition:all .3s ease}.operation-card[data-v-de75772f]:hover{box-shadow:0 4px 16px #0000001f;transform:translateY(-2px)}.operation-card.configured[data-v-de75772f]:before{background:linear-gradient(90deg,#10b981,#059669)}.operation-card.configured[data-v-de75772f]{border-color:#10b9814d;background:linear-gradient(135deg,#fffffffa,#f0fdf499)}.operation-card.disabled[data-v-de75772f]{opacity:.6;background:#f8fafccc}.operation-card.testing[data-v-de75772f]:before{background:linear-gradient(90deg,#3b82f6,#2563eb)}.operation-card.testing[data-v-de75772f]{border-color:#3b82f64d;background:linear-gradient(135deg,#fffffffa,#eff6ff99)}.card-header[data-v-de75772f]{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px}.operation-info[data-v-de75772f]{display:flex;align-items:center;gap:10px;flex:1}.operation-icon[data-v-de75772f]{width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:8px;background:linear-gradient(135deg,#f8fafc,#f1f5f9);border:1px solid rgba(226,232,240,.6);box-shadow:0 1px 4px #0000000a}.provider-icon-large[data-v-de75772f]{width:24px;height:24px;object-fit:contain}.default-icon[data-v-de75772f]{font-size:18px}.operation-details[data-v-de75772f]{flex:1}.operation-name[data-v-de75772f]{font-size:15px;font-weight:700;color:#1e293b;margin:0 0 4px;line-height:1.2}.operation-desc[data-v-de75772f]{font-size:12px;color:#64748b;margin:0;line-height:1.4}.status-badge[data-v-de75772f]{padding:4px 8px;border-radius:6px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.status-badge.configured[data-v-de75772f]{background:linear-gradient(135deg,#dcfce7,#bbf7d0);color:#166534;border:1px solid rgba(187,247,208,.6)}.status-badge.pending[data-v-de75772f]{background:linear-gradient(135deg,#fef3c7,#fde68a);color:#92400e;border:1px solid rgba(253,230,138,.6)}.status-badge.disabled[data-v-de75772f]{background:linear-gradient(135deg,#f1f5f9,#e2e8f0);color:#64748b;border:1px solid rgba(226,232,240,.6)}.model-binding[data-v-de75772f]{margin-bottom:12px}.model-selector[data-v-de75772f]{position:relative}.model-select[data-v-de75772f]{width:100%;padding:8px 12px;border:1px solid rgba(209,213,219,.6);border-radius:8px;font-size:13px;background:#ffffffe6;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all .3s ease;box-shadow:0 1px 4px #0000000a}.model-select[data-v-de75772f]:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a,0 2px 8px #00000014}.model-select.has-value[data-v-de75772f]{border-color:#10b981;background:linear-gradient(135deg,#fffffff2,#f0fdf44d)}.config-summary[data-v-de75772f]{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px;padding:10px;background:linear-gradient(135deg,#f8fafccc,#f1f5f999);border-radius:8px;border:1px solid rgba(226,232,240,.4)}.config-item[data-v-de75772f]{display:flex;align-items:center;gap:4px}.config-label[data-v-de75772f]{font-size:11px;color:#64748b;font-weight:500}.config-value[data-v-de75772f]{font-size:11px;font-weight:600;color:#1e293b}.config-features[data-v-de75772f]{display:flex;gap:6px}.feature-tag[data-v-de75772f]{padding:2px 6px;border-radius:4px;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.feature-tag.json[data-v-de75772f]{background:linear-gradient(135deg,#dbeafe,#bfdbfe);color:#1e40af;border:1px solid rgba(191,219,254,.6)}.feature-tag.thinking[data-v-de75772f]{background:linear-gradient(135deg,#fce7f3,#f9a8d4);color:#be185d;border:1px solid rgba(249,168,212,.6)}.card-actions[data-v-de75772f]{display:flex;gap:6px;justify-content:flex-end}.action-btn[data-v-de75772f]{display:flex;align-items:center;justify-content:center;padding:8px;border:1px solid rgba(226,232,240,.6);border-radius:8px;background:#ffffffe6;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);cursor:pointer;transition:all .3s ease;box-shadow:0 1px 4px #0000000a;position:relative;overflow:hidden}.action-btn.large[data-v-de75772f]{padding:8px;min-width:36px;min-height:36px}.action-btn[data-v-de75772f]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s}.action-btn[data-v-de75772f]:hover:before{left:100%}.action-btn.test[data-v-de75772f]{border-color:#10b98166;color:#10b981}.action-btn.test[data-v-de75772f]:hover{background:linear-gradient(135deg,#10b981,#059669);color:#fff;transform:translateY(-1px);box-shadow:0 2px 8px #10b9814d}.action-btn.edit[data-v-de75772f]{border-color:#3b82f666;color:#3b82f6}.action-btn.edit[data-v-de75772f]:hover{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;transform:translateY(-1px);box-shadow:0 2px 8px #3b82f64d}.action-btn.clear[data-v-de75772f]{border-color:#ef444466;color:#ef4444}.action-btn.clear[data-v-de75772f]:hover{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;transform:translateY(-1px);box-shadow:0 2px 8px #ef44444d}.action-btn[data-v-de75772f]:disabled{opacity:.5;cursor:not-allowed;transform:none}.modal-overlay[data-v-de75772f]{position:fixed;top:0;left:0;right:0;bottom:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn-de75772f .3s ease-out}@keyframes fadeIn-de75772f{0%{opacity:0}to{opacity:1}}.modal-content[data-v-de75772f]{background:#fffffffa;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-radius:12px;box-shadow:0 20px 40px -12px #00000040;max-width:480px;width:90%;max-height:90vh;border:1px solid rgba(255,255,255,.2);animation:slideUp-de75772f .3s ease-out}@keyframes slideUp-de75772f{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.modal-content.wide[data-v-de75772f]{max-width:720px;width:95%}.modal-header[data-v-de75772f]{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(226,232,240,.4)}.modal-header h3[data-v-de75772f]{margin:0;font-size:16px;font-weight:700;background:linear-gradient(135deg,#1e293b,#475569);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.btn-close[data-v-de75772f]{padding:6px;background:#f8fafccc;border:1px solid rgba(226,232,240,.6);color:#64748b;cursor:pointer;border-radius:6px;transition:all .3s ease}.btn-close[data-v-de75772f]:hover{background:#ef44441a;border-color:#ef44444d;color:#ef4444}.modal-body[data-v-de75772f]{padding:20px}.modal-body.compact[data-v-de75772f]{padding:16px 20px}.form-grid[data-v-de75772f]{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-bottom:16px}.form-grid.wide[data-v-de75772f]{grid-template-columns:repeat(3,1fr)}.form-row[data-v-de75772f]{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-bottom:16px}.form-group[data-v-de75772f]{display:flex;flex-direction:column}.form-group.full-width[data-v-de75772f]{grid-column:1 / -1}.form-group.checkbox-group[data-v-de75772f]{flex-direction:row;align-items:center}.form-group label[data-v-de75772f]{font-size:13px;font-weight:600;color:#374151;margin-bottom:6px}.form-input[data-v-de75772f],.form-textarea[data-v-de75772f]{padding:8px 12px;border:1px solid rgba(209,213,219,.6);border-radius:8px;font-size:13px;background:#ffffffe6;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all .3s ease;box-shadow:0 1px 4px #0000000a}.form-input[data-v-de75772f]:focus,.form-textarea[data-v-de75772f]:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a,0 2px 8px #00000014}.checkbox-input[data-v-de75772f]{margin-right:8px;transform:scale(1.1)}.checkbox-label[data-v-de75772f]{display:flex;align-items:center;font-size:13px;cursor:pointer;font-weight:500}.operation-checkboxes[data-v-de75772f]{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;max-height:180px;overflow-y:auto;padding:12px;border:1px solid rgba(226,232,240,.6);border-radius:8px;background:#f8fafc80}.checkbox-item[data-v-de75772f]{display:flex;align-items:center;padding:6px;cursor:pointer;border-radius:4px;transition:all .3s ease;font-size:12px}.checkbox-item[data-v-de75772f]:hover{background:#3b82f61a}.form-actions[data-v-de75772f]{display:flex;justify-content:flex-end;gap:12px;margin-top:16px;padding-top:16px;border-top:1px solid rgba(226,232,240,.4)}.btn-loading[data-v-de75772f]{width:14px;height:14px;border:2px solid transparent;border-top:2px solid currentColor;border-radius:50%;animation:spin-de75772f 1s linear infinite;margin-right:6px}.success-toast[data-v-de75772f]{position:fixed;top:20px;right:20px;background:linear-gradient(135deg,#10b981,#059669);color:#fff;padding:12px 16px;border-radius:8px;display:flex;align-items:center;gap:8px;box-shadow:0 4px 16px #10b9814d;z-index:1001;animation:slideIn-de75772f .4s cubic-bezier(.4,0,.2,1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);font-size:13px}.error-toast[data-v-de75772f]{position:fixed;top:20px;right:20px;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;padding:12px 16px;border-radius:8px;display:flex;align-items:center;gap:8px;box-shadow:0 4px 16px #ef44444d;z-index:1001;animation:slideIn-de75772f .4s cubic-bezier(.4,0,.2,1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);font-size:13px}@keyframes slideIn-de75772f{0%{transform:translate(100%) scale(.9);opacity:0}to{transform:translate(0) scale(1);opacity:1}}@media (max-width: 768px){.content-header[data-v-de75772f]{flex-direction:column;gap:12px;align-items:stretch;padding:12px 16px}.header-right[data-v-de75772f]{flex-direction:column;gap:12px}.header-stats[data-v-de75772f]{justify-content:center;gap:8px}.header-actions[data-v-de75772f]{justify-content:center}.toolbar[data-v-de75772f]{flex-direction:column;gap:12px;align-items:stretch;padding:12px 16px}.search-container[data-v-de75772f]{width:100%}.main-content[data-v-de75772f]{padding:16px}.operations-grid[data-v-de75772f]{grid-template-columns:1fr;gap:12px}.form-grid[data-v-de75772f]{grid-template-columns:1fr}.form-grid.wide[data-v-de75772f]{grid-template-columns:repeat(2,1fr)}.operation-checkboxes[data-v-de75772f]{grid-template-columns:1fr}}@media (max-width: 480px){.header-stats[data-v-de75772f]{grid-template-columns:repeat(2,1fr);gap:6px}.form-grid.wide[data-v-de75772f],.form-row[data-v-de75772f]{grid-template-columns:1fr}.modal-content[data-v-de75772f]{margin:16px;width:calc(100% - 32px)}}@media (prefers-color-scheme: dark){.ai-node-config-content[data-v-de75772f]{background:linear-gradient(135deg,#0f172a,#1e293b)}.content-header[data-v-de75772f]{background:#1e293bf2;border-bottom-color:#47556999}.header-left h2[data-v-de75772f]{background:linear-gradient(135deg,#f8fafc,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent}.operation-card[data-v-de75772f]{background:#1e293bf2;border-color:#47556999}.modal-content[data-v-de75772f]{background:#1e293bfa;border-color:#47556966}}.content-header[data-v-038ec4b3]{margin-bottom:2rem}.content-header h2[data-v-038ec4b3]{font-size:2rem;font-weight:700;color:#2d3748;margin:0 0 .5rem}.content-header p[data-v-038ec4b3]{font-size:1.1rem;color:#718096;margin:0}.system-content .system-operations[data-v-038ec4b3]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:2rem}.operation-card[data-v-038ec4b3]{background:#fffc;border-radius:16px;padding:2rem;box-shadow:0 4px 16px #0000000d;border:1px solid rgba(0,0,0,.05);display:flex;flex-direction:column;align-items:center;text-align:center;gap:1rem}.operation-card .card-icon[data-v-038ec4b3]{width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;font-size:2rem;color:#fff}.operation-card .card-content h3[data-v-038ec4b3]{font-size:1.25rem;font-weight:600;color:#2d3748;margin:0 0 .5rem}.operation-card .card-content p[data-v-038ec4b3]{font-size:1rem;color:#718096;margin:0 0 1rem}.btn[data-v-038ec4b3]{padding:.75rem 1.5rem;border:none;border-radius:8px;font-weight:600;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem;text-decoration:none;font-size:1rem}.btn[data-v-038ec4b3]:disabled{opacity:.6;cursor:not-allowed}.btn-primary[data-v-038ec4b3]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}.btn-primary[data-v-038ec4b3]:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 4px 12px #667eea66}.btn-secondary[data-v-038ec4b3]{background:#e2e8f0;color:#4a5568}.btn-secondary[data-v-038ec4b3]:hover:not(:disabled){background:#cbd5e0}.btn-danger[data-v-038ec4b3]{background:#fed7d7;color:#742a2a}.btn-danger[data-v-038ec4b3]:hover:not(:disabled){background:#feb2b2}.btn-loading[data-v-038ec4b3]{width:16px;height:16px;border:2px solid transparent;border-top:2px solid currentColor;border-radius:50%;animation:spin-038ec4b3 1s linear infinite}@keyframes spin-038ec4b3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (max-width: 768px){.system-operations[data-v-038ec4b3]{grid-template-columns:1fr}}.json-viewer[data-v-6b3d677c]{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;background:#fff;font-family:SF Mono,Monaco,Menlo,Ubuntu Mono,monospace;font-size:13px}.json-toolbar[data-v-6b3d677c]{display:flex;align-items:center;padding:8px 12px;background:linear-gradient(135deg,#f8fafc,#f1f5f9);border-bottom:1px solid #e2e8f0;gap:12px;min-height:40px}.toolbar-left[data-v-6b3d677c]{display:flex;gap:6px}.toolbar-center[data-v-6b3d677c]{flex:1;display:flex;justify-content:center}.toolbar-right[data-v-6b3d677c]{display:flex;align-items:center;gap:8px;font-size:11px;color:#64748b}.tool-btn[data-v-6b3d677c]{display:flex;align-items:center;gap:4px;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;background:#fff;color:#6b7280;font-size:11px;font-weight:500;cursor:pointer;transition:all .15s ease;height:24px}.tool-btn[data-v-6b3d677c]:hover{background:#f9fafb;border-color:#9ca3af;color:#374151}.tool-btn.active[data-v-6b3d677c]{background:#3b82f6;color:#fff;border-color:#3b82f6}.tool-btn.success[data-v-6b3d677c]{background:#10b981;color:#fff;border-color:#10b981}.tool-btn svg[data-v-6b3d677c]{width:12px;height:12px}.search-box[data-v-6b3d677c]{position:relative;display:flex;align-items:center;max-width:200px}.search-box svg[data-v-6b3d677c]{position:absolute;left:8px;width:12px;height:12px;color:#9ca3af;z-index:1}.search-input[data-v-6b3d677c]{width:100%;padding:4px 24px;border:1px solid #d1d5db;border-radius:4px;font-size:11px;background:#fff;outline:none;transition:border-color .15s ease}.search-input[data-v-6b3d677c]:focus{border-color:#3b82f6}.clear-search[data-v-6b3d677c]{position:absolute;right:4px;background:none;border:none;cursor:pointer;padding:2px;color:#9ca3af;display:flex;align-items:center}.clear-search svg[data-v-6b3d677c]{width:10px;height:10px}.path-display[data-v-6b3d677c]{font-family:inherit;color:#3b82f6;font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.size-info[data-v-6b3d677c],.item-count[data-v-6b3d677c]{font-weight:600;color:#64748b}.json-content[data-v-6b3d677c]{max-height:var(--1b6c152d);overflow:auto;scrollbar-width:thin;scrollbar-color:#cbd5e1 transparent}.json-content[data-v-6b3d677c]::-webkit-scrollbar{width:6px;height:6px}.json-content[data-v-6b3d677c]::-webkit-scrollbar-track{background:transparent}.json-content[data-v-6b3d677c]::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.json-raw[data-v-6b3d677c]{padding:16px;white-space:pre-wrap;word-break:break-all;color:#374151;line-height:1.5}.json-formatted[data-v-6b3d677c]{padding:16px;line-height:1.4;color:#374151;white-space:pre;overflow-x:auto}[data-v-6b3d677c] .json-string{color:#059669;font-weight:500}[data-v-6b3d677c] .json-number{color:#dc2626;font-weight:600}[data-v-6b3d677c] .json-boolean{color:#7c3aed;font-weight:600}[data-v-6b3d677c] .json-null,[data-v-6b3d677c] .json-undefined{color:#6b7280;font-style:italic;font-weight:500}[data-v-6b3d677c] .json-key{color:#1e40af;font-weight:600}[data-v-6b3d677c] .json-bracket{color:#374151;font-weight:700}[data-v-6b3d677c] .json-colon{color:#6b7280;margin:0 4px}[data-v-6b3d677c] .json-toggle{cursor:pointer;color:#6b7280;margin-right:4px;font-size:10px;transition:color .15s ease;-webkit-user-select:none;user-select:none}[data-v-6b3d677c] .json-toggle:hover{color:#374151}[data-v-6b3d677c] .json-preview{color:#9ca3af;font-style:italic;margin:0 4px;font-size:11px}[data-v-6b3d677c] .search-highlight{background:#fef3c7;padding:1px 2px;border-radius:2px;box-shadow:0 0 0 1px #f59e0b}@media (max-width: 768px){.json-toolbar[data-v-6b3d677c]{flex-wrap:wrap;gap:8px}.toolbar-center[data-v-6b3d677c]{order:3;flex-basis:100%;justify-content:flex-start}.search-box[data-v-6b3d677c]{max-width:none;width:100%}.path-display[data-v-6b3d677c]{display:none}}.log-detail-page[data-v-7246130a]{height:100vh;background:radial-gradient(ellipse at top,#f8fafc,#f1f5f9,#e2e8f0);display:flex;flex-direction:column;overflow:hidden;position:relative}.log-detail-page[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;height:200px;background:linear-gradient(135deg,#3b82f608,#93c5fd05);pointer-events:none}.top-nav[data-v-7246130a]{background:#fffffffa;-webkit-backdrop-filter:blur(20px) saturate(180%);backdrop-filter:blur(20px) saturate(180%);border-bottom:1px solid rgba(226,232,240,.6);padding:1.5rem 2rem;display:flex;align-items:center;gap:1.5rem;flex-shrink:0;box-shadow:0 1px 3px #00000008,0 1px 2px #00000005;position:relative;z-index:10}.nav-back[data-v-7246130a]{background:linear-gradient(135deg,#fff,#f8fafc);border:1px solid rgba(226,232,240,.8);display:flex;align-items:center;gap:.625rem;color:#475569;font-weight:600;cursor:pointer;padding:.75rem 1.25rem;border-radius:10px;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 1px 3px #0000000a,0 1px 2px #00000005;position:relative;overflow:hidden}.nav-back[data-v-7246130a]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);transition:left .5s}.nav-back[data-v-7246130a]:hover:before{left:100%}.nav-back[data-v-7246130a]:hover{background:linear-gradient(135deg,#f1f5f9,#e2e8f0);color:#1e293b;transform:translateY(-2px);box-shadow:0 4px 12px #00000014,0 2px 4px #0000000a}.nav-back svg[data-v-7246130a]{width:18px;height:18px;stroke-width:2.5;transition:transform .3s ease}.nav-back:hover svg[data-v-7246130a]{transform:translate(-2px)}.nav-title[data-v-7246130a]{flex:1;display:flex;align-items:center;justify-content:space-between}.nav-title h1[data-v-7246130a]{font-size:1.5rem;font-weight:800;margin:0;background:linear-gradient(135deg,#0f172a,#334155,#64748b);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-.025em}.status-badge[data-v-7246130a]{padding:.625rem 1.25rem;border-radius:10px;font-size:.875rem;font-weight:700;display:flex;align-items:center;gap:.5rem;box-shadow:0 2px 8px #0000000f,0 1px 3px #0000000a;position:relative;overflow:hidden}.status-badge[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;opacity:.1;background:radial-gradient(circle at center,currentColor 0%,transparent 70%)}.status-badge.success[data-v-7246130a]{background:linear-gradient(135deg,#dcfce7,#bbf7d0,#a7f3d0);color:#15803d;border:1px solid rgba(134,239,172,.6)}.status-badge.failed[data-v-7246130a]{background:linear-gradient(135deg,#fef2f2,#fecaca,#fca5a5);color:#dc2626;border:1px solid rgba(252,165,165,.6)}.status-icon[data-v-7246130a]{width:8px;height:8px;border-radius:50%;background:currentColor;box-shadow:0 0 8px currentColor;animation:pulse-7246130a 2s infinite}@keyframes pulse-7246130a{0%,to{opacity:1}50%{opacity:.6}}.content-wrapper[data-v-7246130a]{flex:1;padding:2rem;overflow:hidden}.loading-container[data-v-7246130a]{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.5rem;height:100%;color:#64748b;font-weight:600}.spinner-container[data-v-7246130a]{position:relative;width:48px;height:48px}.spinner[data-v-7246130a]{width:48px;height:48px;border:4px solid rgba(59,130,246,.1);border-top:4px solid #3b82f6;border-radius:50%;animation:spin-7246130a 1s linear infinite;position:relative;z-index:2}.spinner-glow[data-v-7246130a]{position:absolute;top:-4px;left:-4px;width:56px;height:56px;border-radius:50%;background:radial-gradient(circle,rgba(59,130,246,.2) 0%,transparent 70%);animation:glow-7246130a 2s ease-in-out infinite alternate}@keyframes spin-7246130a{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes glow-7246130a{0%{transform:scale(1);opacity:.5}to{transform:scale(1.1);opacity:.8}}.loading-text[data-v-7246130a]{font-size:1rem;letter-spacing:.025em}.detail-layout[data-v-7246130a]{display:grid;grid-template-columns:380px 1fr;gap:2rem;height:100%;overflow:hidden}.info-sidebar[data-v-7246130a]{display:flex;flex-direction:column;gap:1rem;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(203,213,225,.6) transparent}.info-sidebar[data-v-7246130a]::-webkit-scrollbar{width:6px}.info-sidebar[data-v-7246130a]::-webkit-scrollbar-track{background:transparent}.info-sidebar[data-v-7246130a]::-webkit-scrollbar-thumb{background:#cbd5e199;border-radius:3px}.info-card[data-v-7246130a]{background:#fffffffa;-webkit-backdrop-filter:blur(20px) saturate(180%);backdrop-filter:blur(20px) saturate(180%);border-radius:16px;border:1px solid rgba(226,232,240,.6);overflow:hidden;box-shadow:0 8px 32px #0000000a,0 4px 16px #00000005;transition:all .4s cubic-bezier(.4,0,.2,1);position:relative}.info-card[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.2),transparent)}.info-card[data-v-7246130a]:hover{box-shadow:0 12px 48px #00000014,0 6px 24px #0000000a;transform:translateY(-2px)}.card-title[data-v-7246130a]{background:linear-gradient(135deg,#f8fafc,#f1f5f9);padding:.875rem 1.25rem;font-size:.8125rem;font-weight:800;color:#374151;border-bottom:1px solid rgba(226,232,240,.6);letter-spacing:.05em;display:flex;align-items:center;gap:.625rem}.title-icon[data-v-7246130a]{font-size:1rem;filter:grayscale(.2)}.info-list[data-v-7246130a]{padding:0}.info-item[data-v-7246130a]{padding:.875rem 1.25rem;border-bottom:1px solid rgba(241,245,249,.6);display:flex;flex-direction:column;gap:.5rem;transition:all .3s ease;position:relative}.info-item[data-v-7246130a]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:0;background:linear-gradient(135deg,#3b82f6,#1d4ed8);transition:width .3s ease}.info-item[data-v-7246130a]:hover:before{width:3px}.info-item[data-v-7246130a]:hover{background:#f8fafccc}.info-item[data-v-7246130a]:last-child{border-bottom:none}.label[data-v-7246130a]{font-size:.6875rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.1em;line-height:1.2}.call-id[data-v-7246130a]{font-family:SF Mono,Monaco,Menlo,monospace;font-size:.75rem;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);padding:.5rem .75rem;border-radius:8px;color:#475569;word-break:break-all;border:1px solid rgba(226,232,240,.8);font-weight:600;position:relative;overflow:hidden}.call-id[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(45deg,transparent 30%,rgba(255,255,255,.3) 50%,transparent 70%);transform:translate(-100%);transition:transform .6s}.call-id[data-v-7246130a]:hover:before{transform:translate(100%)}.operation-badge[data-v-7246130a]{background:linear-gradient(135deg,#dbeafe,#bfdbfe,#93c5fd);color:#1e40af;padding:.5rem 1rem;border-radius:8px;font-size:.75rem;font-weight:800;align-self:flex-start;border:1px solid rgba(147,197,253,.6);box-shadow:0 2px 8px #3b82f626;position:relative;overflow:hidden}.operation-badge[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(135deg,rgba(255,255,255,.3),transparent);opacity:0;transition:opacity .3s}.operation-badge[data-v-7246130a]:hover:before{opacity:1}.model-info[data-v-7246130a]{display:flex;align-items:center;gap:1rem}.provider-icon-wrapper[data-v-7246130a]{position:relative;padding:4px;background:linear-gradient(135deg,#f8fafc,#f1f5f9);border-radius:10px;box-shadow:0 2px 8px #0000000f}.provider-icon[data-v-7246130a]{width:32px;height:32px;border-radius:6px;object-fit:contain;flex-shrink:0;transition:transform .3s ease}.provider-icon-wrapper:hover .provider-icon[data-v-7246130a]{transform:scale(1.05)}.model-details[data-v-7246130a]{flex:1;min-width:0}.model-name[data-v-7246130a]{font-size:.875rem;font-weight:800;color:#0f172a;line-height:1.4;word-break:break-all;margin-bottom:2px}.provider-name[data-v-7246130a]{font-size:.75rem;color:#64748b;line-height:1.4;font-weight:600}.time-value[data-v-7246130a]{font-size:.875rem;color:#0f172a;font-weight:700;font-family:SF Mono,Monaco,Menlo,monospace;letter-spacing:-.025em}.duration-badge[data-v-7246130a]{padding:.5rem 1rem;border-radius:8px;font-size:.75rem;font-weight:800;align-self:flex-start;font-family:SF Mono,Monaco,Menlo,monospace;border:1px solid;box-shadow:0 2px 8px #00000014;display:flex;align-items:center;gap:.5rem;position:relative;overflow:hidden}.duration-icon[data-v-7246130a]{width:6px;height:6px;border-radius:50%;background:currentColor;box-shadow:0 0 6px currentColor}.duration-badge.fast[data-v-7246130a]{background:#c6f6d5;color:#22543d;border-color:#86efac99}.duration-badge.normal[data-v-7246130a]{background:#faf089;color:#744210;border-color:#fbbf2499}.duration-badge.slow[data-v-7246130a]{background:#fed7d7;color:#742a2a;border-color:#fca5a599}.params-grid[data-v-7246130a]{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#f1f5f999}.param-item[data-v-7246130a]{background:#fffc;padding:1rem 1.25rem;display:flex;flex-direction:column;gap:.5rem;transition:all .3s ease;position:relative}.param-item[data-v-7246130a]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:0;background:linear-gradient(135deg,#3b82f6,#1d4ed8);transition:width .3s ease}.param-item[data-v-7246130a]:hover:before{width:2px}.param-item[data-v-7246130a]:hover{background:#f8fafce6}.param-label[data-v-7246130a]{font-size:.75rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.05em}.param-value[data-v-7246130a]{font-size:.875rem;font-weight:800;color:#0f172a;font-family:SF Mono,Monaco,Menlo,monospace}.param-toggle[data-v-7246130a]{display:flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:700;padding:.25rem .5rem;border-radius:6px;align-self:flex-start}.toggle-indicator[data-v-7246130a]{width:8px;height:8px;border-radius:50%;transition:all .3s ease}.param-toggle.enabled[data-v-7246130a]{color:#059669;background:#dcfce799}.param-toggle.enabled .toggle-indicator[data-v-7246130a]{background:#10b981;box-shadow:0 0 8px #10b98166}.param-toggle.disabled[data-v-7246130a]{color:#64748b;background:#f1f5f999}.param-toggle.disabled .toggle-indicator[data-v-7246130a]{background:#94a3b8}.content-area[data-v-7246130a]{display:flex;flex-direction:column;overflow:hidden}.content-tabs[data-v-7246130a]{display:flex;background:#fffffffa;-webkit-backdrop-filter:blur(20px) saturate(180%);backdrop-filter:blur(20px) saturate(180%);border-radius:16px 16px 0 0;border:1px solid rgba(226,232,240,.6);border-bottom:none;overflow-x:auto;box-shadow:0 4px 16px #0000000a;position:relative}.content-tabs[data-v-7246130a]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.2),transparent)}.tab-btn[data-v-7246130a]{background:none;border:none;padding:0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);border-bottom:3px solid transparent;position:relative;overflow:hidden}.tab-content[data-v-7246130a]{padding:1.25rem 1.5rem;display:flex;align-items:center;gap:.75rem;white-space:nowrap}.tab-label[data-v-7246130a]{font-size:.875rem;font-weight:700;color:#64748b;transition:color .3s ease}.tab-btn:hover .tab-label[data-v-7246130a]{color:#334155}.tab-btn.active .tab-label[data-v-7246130a]{color:#3b82f6;font-weight:800}.tab-btn.active[data-v-7246130a]{border-bottom-color:#3b82f6;background:#f8fafccc}.tab-indicator[data-v-7246130a]{position:relative;width:8px;height:8px}.indicator-pulse[data-v-7246130a]{width:8px;height:8px;background:linear-gradient(135deg,#10b981,#059669);border-radius:50%;animation:pulse-glow-7246130a 2s infinite;position:relative}.indicator-pulse[data-v-7246130a]:before{content:"";position:absolute;top:-2px;left:-2px;right:-2px;bottom:-2px;background:radial-gradient(circle,rgba(16,185,129,.3) 0%,transparent 70%);border-radius:50%;animation:pulse-glow-7246130a 2s infinite}@keyframes pulse-glow-7246130a{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.2);opacity:.7}}.content-display[data-v-7246130a]{flex:1;background:#fffffffa;-webkit-backdrop-filter:blur(20px) saturate(180%);backdrop-filter:blur(20px) saturate(180%);border:1px solid rgba(226,232,240,.6);border-radius:0 0 16px 16px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 32px #0000000a}.content-block[data-v-7246130a]{height:100%;display:flex;flex-direction:column}.content-block.error[data-v-7246130a]{border-color:#fca5a599}.content-header[data-v-7246130a]{background:linear-gradient(135deg,#f8fafc,#f1f5f9);padding:1.25rem 1.5rem;border-bottom:1px solid rgba(226,232,240,.6);display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.header-left[data-v-7246130a]{display:flex;align-items:center;gap:.75rem}.content-icon[data-v-7246130a]{font-size:1.125rem;filter:grayscale(.2)}.content-icon.error-icon[data-v-7246130a]{filter:none}.content-header h3[data-v-7246130a]{margin:0;font-size:.875rem;font-weight:800;color:#374151;letter-spacing:.025em}.copy-btn[data-v-7246130a]{display:flex;align-items:center;gap:.625rem;background:linear-gradient(135deg,#fff,#f8fafc);border:1px solid rgba(209,213,219,.8);border-radius:8px;padding:.625rem 1rem;font-size:.75rem;color:#6b7280;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);font-weight:700;box-shadow:0 1px 3px #0000000a;position:relative;overflow:hidden}.copy-btn[data-v-7246130a]:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.6),transparent);transition:left .5s}.copy-btn[data-v-7246130a]:hover:before{left:100%}.copy-btn[data-v-7246130a]:hover{background:linear-gradient(135deg,#f9fafb,#f3f4f6);border-color:#9ca3af;color:#374151;transform:translateY(-1px);box-shadow:0 4px 12px #00000014}.copy-btn svg[data-v-7246130a]{width:16px;height:16px;stroke-width:2.5;transition:transform .3s ease}.copy-btn:hover svg[data-v-7246130a]{transform:scale(1.1)}.content-body[data-v-7246130a]{flex:1;overflow:hidden;position:relative}.code-content[data-v-7246130a],.text-content[data-v-7246130a]{width:100%;height:100%;padding:1.5rem;font-family:SF Mono,Monaco,Menlo,Ubuntu Mono,monospace;font-size:.8rem;line-height:1.7;color:#374151;background:linear-gradient(135deg,#f8fafc,#f1f5f9);white-space:pre-wrap;word-break:break-word;overflow-y:auto;margin:0;border:none;scrollbar-width:thin;scrollbar-color:rgba(203,213,225,.6) transparent;resize:none}.code-content[data-v-7246130a]::-webkit-scrollbar,.text-content[data-v-7246130a]::-webkit-scrollbar{width:8px}.code-content[data-v-7246130a]::-webkit-scrollbar-track,.text-content[data-v-7246130a]::-webkit-scrollbar-track{background:transparent}.code-content[data-v-7246130a]::-webkit-scrollbar-thumb,.text-content[data-v-7246130a]::-webkit-scrollbar-thumb{background:#cbd5e199;border-radius:4px}.error-content[data-v-7246130a]{width:100%;height:100%;padding:1.5rem;background:linear-gradient(135deg,#fef2f2,#fee2e2);color:#dc2626;font-family:SF Mono,Monaco,Menlo,Ubuntu Mono,monospace;font-size:.8rem;line-height:1.7;white-space:pre-wrap;word-break:break-word;overflow-y:auto;border:1px solid rgba(252,165,165,.4);border-radius:8px;margin:.75rem;font-weight:600}.empty-state[data-v-7246130a]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#64748b;gap:1.5rem;padding:3rem}.empty-illustration[data-v-7246130a]{position:relative;display:flex;align-items:center;justify-content:center}.empty-circle[data-v-7246130a]{position:absolute;width:80px;height:80px;border:2px solid rgba(203,213,225,.3);border-radius:50%;animation:rotate-7246130a 8s linear infinite}.empty-icon[data-v-7246130a]{font-size:2.5rem;opacity:.7;filter:grayscale(.3);z-index:1}@keyframes rotate-7246130a{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.empty-text[data-v-7246130a]{font-size:.875rem;font-weight:600;margin:0;letter-spacing:.025em}@media (max-width: 1200px){.detail-layout[data-v-7246130a]{grid-template-columns:320px 1fr}}@media (max-width: 1024px){.detail-layout[data-v-7246130a]{grid-template-columns:1fr;grid-template-rows:auto 1fr}.info-sidebar[data-v-7246130a]{max-height:350px}.params-grid[data-v-7246130a]{grid-template-columns:1fr}}@media (max-width: 768px){.content-wrapper[data-v-7246130a]{padding:1rem}.top-nav[data-v-7246130a]{padding:1rem 1.5rem}.nav-title[data-v-7246130a]{flex-direction:column;align-items:flex-start;gap:1rem}.detail-layout[data-v-7246130a]{gap:1.5rem}.info-card[data-v-7246130a],.content-tabs[data-v-7246130a],.content-display[data-v-7246130a]{border-radius:12px}.content-tabs[data-v-7246130a]{border-radius:12px 12px 0 0}.content-display[data-v-7246130a]{border-radius:0 0 12px 12px}}.ai-log-content[data-v-584cc492]{padding:0;background:transparent}.content-header[data-v-584cc492]{display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;padding:0}.content-header h2[data-v-584cc492]{font-size:1.5rem;font-weight:600;color:#2d3748;margin:0}.header-actions[data-v-584cc492]{display:flex;gap:.75rem}.btn[data-v-584cc492]{display:flex;align-items:center;gap:.375rem;padding:.5rem 1rem;border-radius:6px;font-weight:500;transition:all .2s ease;border:none;cursor:pointer;font-size:.875rem}.btn-secondary[data-v-584cc492]{background:#ffffffe6;color:#4a5568;border:1px solid #e2e8f0}.btn-secondary[data-v-584cc492]:hover:not(:disabled){background:#f7fafc;border-color:#cbd5e0}.btn-danger[data-v-584cc492]{background:#e53e3e;color:#fff}.btn-danger[data-v-584cc492]:hover:not(:disabled){background:#c53030}.btn[data-v-584cc492]:disabled{opacity:.6;cursor:not-allowed}.main-content[data-v-584cc492]{background:#fffffff2;border-radius:12px;padding:1.5rem;box-shadow:0 4px 16px #00000014;border:1px solid rgba(255,255,255,.2)}.loading-state[data-v-584cc492],.empty-state[data-v-584cc492]{text-align:center;padding:3rem 2rem}.loading-spinner[data-v-584cc492]{width:32px;height:32px;border:3px solid #e2e8f0;border-top:3px solid #667eea;border-radius:50%;animation:spin-584cc492 1s linear infinite;margin:0 auto 1rem}@keyframes spin-584cc492{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.empty-icon[data-v-584cc492]{font-size:3rem;margin-bottom:1rem}.empty-state h3[data-v-584cc492]{color:#2d3748;margin-bottom:.5rem;font-size:1.125rem}.empty-state p[data-v-584cc492]{color:#718096;font-size:.875rem}.list-header[data-v-584cc492]{margin-bottom:1rem}.header-info[data-v-584cc492]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.log-count[data-v-584cc492]{color:#718096;font-size:.875rem;font-weight:500}.search-box[data-v-584cc492]{position:relative;display:flex;align-items:center}.search-icon[data-v-584cc492]{position:absolute;left:.75rem;width:1rem;height:1rem;color:#a0aec0;z-index:1}.search-input[data-v-584cc492]{padding:.5rem .75rem .5rem 2.25rem;border:1px solid #e2e8f0;border-radius:6px;font-size:.875rem;width:200px;transition:border-color .2s ease}.search-input[data-v-584cc492]:focus{outline:none;border-color:#667eea;box-shadow:0 0 0 3px #667eea1a}.filter-controls[data-v-584cc492]{display:flex;gap:.75rem;align-items:center}.filter-select[data-v-584cc492]{padding:.5rem .75rem;border:1px solid #e2e8f0;border-radius:6px;font-size:.875rem;background:#fff;transition:border-color .2s ease}.filter-select[data-v-584cc492]:focus{outline:none;border-color:#667eea}.table-container[data-v-584cc492]{border-radius:8px;overflow:hidden;border:1px solid #e2e8f0;background:#fff}.table-header[data-v-584cc492]{display:grid;grid-template-columns:140px 100px 400px 2fr 100px 80px;gap:0;background:linear-gradient(135deg,#f8fafc,#f1f5f9);border-bottom:2px solid #e2e8f0}.header-cell[data-v-584cc492]{padding:1rem .75rem;font-weight:600;color:#4a5568;font-size:.875rem;text-align:left;border-right:1px solid #e2e8f0}.header-cell[data-v-584cc492]:last-child{border-right:none}.table-body[data-v-584cc492]{background:#fff}.table-row[data-v-584cc492]{display:grid;grid-template-columns:140px 100px 400px 2fr 100px 80px;gap:0;border-bottom:1px solid #f1f5f9;transition:all .2s ease;position:relative}.table-row[data-v-584cc492]:hover{background:linear-gradient(135deg,#f8fafc,#f1f5f9);transform:translateY(-1px);box-shadow:0 2px 8px #0000000d}.table-row[data-v-584cc492]:last-child{border-bottom:none}.table-row.row-failed[data-v-584cc492]{background:linear-gradient(135deg,#fef5e7,#fed7aa);border-left:4px solid #f56565}.table-row.row-failed[data-v-584cc492]:hover{background:linear-gradient(135deg,#fed7aa,#fbb6ce)}.cell[data-v-584cc492]{padding:1rem .75rem;display:flex;align-items:center;border-right:1px solid #f1f5f9;min-height:60px}.cell[data-v-584cc492]:last-child{border-right:none}.time-info[data-v-584cc492]{display:flex;flex-direction:column;gap:.25rem}.time-relative[data-v-584cc492]{font-size:.875rem;font-weight:500;color:#2d3748}.time-full[data-v-584cc492]{font-size:.75rem;color:#718096}.model-info[data-v-584cc492]{display:flex;align-items:center;gap:.75rem;width:100%}.model-avatar[data-v-584cc492]{width:36px;height:36px;border-radius:8px;background:linear-gradient(135deg,#f7fafc,#edf2f7);display:flex;align-items:center;justify-content:center;border:1px solid #e2e8f0;flex-shrink:0;box-shadow:0 2px 4px #0000000d}.provider-icon[data-v-584cc492]{width:20px;height:20px;object-fit:contain}.model-details[data-v-584cc492]{flex:1;min-width:0}.model-name[data-v-584cc492]{font-size:.875rem;font-weight:600;color:#2d3748;margin:0 0 .25rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.provider-name[data-v-584cc492]{font-size:.75rem;color:#718096;font-weight:500}.operation-tag[data-v-584cc492]{display:inline-flex;align-items:center;padding:.375rem .75rem;border-radius:6px;font-size:.75rem;font-weight:600;background:linear-gradient(135deg,#e6f3ff,#cce7ff);color:#2b6cb0;border:1px solid #90cdf4}.duration-value[data-v-584cc492]{font-size:.875rem;font-weight:600;padding:.25rem .5rem;border-radius:4px}.duration-fast[data-v-584cc492]{color:#22543d;background:#c6f6d5}.duration-normal[data-v-584cc492]{color:#744210;background:#faf089}.duration-slow[data-v-584cc492]{color:#742a2a;background:#fed7d7}.duration-unknown[data-v-584cc492]{color:#718096;background:#edf2f7}.status-indicator[data-v-584cc492]{display:flex;align-items:center;gap:.5rem;font-size:.875rem;font-weight:500}.status-dot[data-v-584cc492]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.status-indicator.success .status-dot[data-v-584cc492]{background:#48bb78;box-shadow:0 0 0 2px #48bb7833}.status-indicator.success[data-v-584cc492]{color:#22543d}.status-indicator.failed .status-dot[data-v-584cc492]{background:#f56565;box-shadow:0 0 0 2px #f5656533}.status-indicator.failed[data-v-584cc492]{color:#742a2a}.actions-cell[data-v-584cc492]{justify-content:center}.action-btn[data-v-584cc492]{width:36px;height:36px;border-radius:8px;border:1px solid #e2e8f0;background:linear-gradient(135deg,#fff,#f7fafc);color:#718096;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 4px #0000000d}.action-btn[data-v-584cc492]:hover{background:linear-gradient(135deg,#e6f3ff,#cce7ff);border-color:#90cdf4;color:#2b6cb0;transform:translateY(-1px);box-shadow:0 4px 8px #0000001a}.pagination[data-v-584cc492]{display:flex;justify-content:center;align-items:center;gap:1rem;margin-top:1.5rem;padding-top:1rem;border-top:1px solid #e2e8f0}.page-btn[data-v-584cc492]{padding:.5rem 1rem;border:1px solid #e2e8f0;background:#fff;color:#4a5568;border-radius:6px;cursor:pointer;transition:all .2s ease;font-size:.875rem}.page-btn[data-v-584cc492]:hover:not(:disabled){background:#f7fafc;border-color:#cbd5e0}.page-btn[data-v-584cc492]:disabled{opacity:.5;cursor:not-allowed}.page-info[data-v-584cc492]{color:#718096;font-size:.875rem}@media (max-width: 1200px){.table-header[data-v-584cc492],.table-row[data-v-584cc492]{grid-template-columns:120px 80px 250px 2fr 80px 60px}}@media (max-width: 768px){.content-header[data-v-584cc492]{flex-direction:column;gap:1rem;align-items:flex-start}.header-actions[data-v-584cc492]{width:100%;justify-content:flex-end}.list-header[data-v-584cc492]{flex-direction:column;gap:1rem}.header-info[data-v-584cc492]{flex-direction:column;gap:.75rem;align-items:flex-start}.filter-controls[data-v-584cc492]{flex-wrap:wrap;gap:.5rem}.table-header[data-v-584cc492],.table-row[data-v-584cc492]{grid-template-columns:100px 80px 120px 1fr 80px 60px}.search-input[data-v-584cc492]{width:150px}.model-name[data-v-584cc492]{font-size:.75rem}.provider-name[data-v-584cc492]{font-size:.65rem}}.api-config[data-v-6f5fc07f]{min-height:100vh;background:linear-gradient(135deg,#f5f7fa,#c3cfe2);padding:1rem}.main-content[data-v-6f5fc07f]{display:flex;gap:0;height:calc(100vh - 160px)}@media (max-width: 768px){.main-content[data-v-6f5fc07f]{flex-direction:column;height:auto}.sidebar[data-v-6f5fc07f]{width:100%;border-radius:16px;border:1px solid rgba(255,255,255,.2);margin-bottom:1rem}.divider[data-v-6f5fc07f]{display:none}.content-area[data-v-6f5fc07f]{width:100%;border-radius:16px;border:1px solid rgba(255,255,255,.2)}.stats-grid[data-v-6f5fc07f]{grid-template-columns:repeat(3,1fr);gap:.25rem}.stat-item[data-v-6f5fc07f]{flex-direction:column;text-align:center;padding:.5rem}.stat-value[data-v-6f5fc07f]{font-size:1rem;margin-bottom:.25rem}.stat-label[data-v-6f5fc07f]{font-size:.65rem}}.sidebar[data-v-6f5fc07f]{width:15%;background:#ffffffe6;border-radius:16px 0 0 16px;padding:2rem 1.5rem;box-shadow:0 4px 16px #0000000d;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);border-right:none;overflow-y:auto;display:flex;flex-direction:column}.tab-navigation[data-v-6f5fc07f]{flex:1}.tab-header[data-v-6f5fc07f]{margin-bottom:1.5rem}.tab-header h3[data-v-6f5fc07f]{font-size:1.25rem;font-weight:600;color:#2d3748;margin:0}.tab-list[data-v-6f5fc07f]{display:flex;flex-direction:column;gap:.5rem}.tab-item[data-v-6f5fc07f]{position:relative;padding:1rem;border-radius:12px;cursor:pointer;transition:all .3s ease;border:2px solid transparent;display:flex;align-items:center;gap:1rem}.tab-item[data-v-6f5fc07f]:hover{background:#667eea0d;border-color:#667eea33}.tab-item.active[data-v-6f5fc07f]{background:linear-gradient(135deg,#667eea1a,#764ba21a);border-color:#667eea;box-shadow:0 4px 12px #667eea33}.tab-icon[data-v-6f5fc07f]{min-width:2rem;text-align:center;display:flex;align-items:center;justify-content:center}.icon-svg[data-v-6f5fc07f]{width:24px;height:24px;color:#718096;transition:all .3s ease;display:flex;align-items:center;justify-content:center}.icon-svg svg[data-v-6f5fc07f]{width:100%;height:100%;transition:all .3s ease}.tab-item:hover .icon-svg[data-v-6f5fc07f]{color:#667eea;transform:scale(1.1)}.tab-item.active .icon-svg[data-v-6f5fc07f]{color:#667eea;transform:scale(1.15)}.tab-item.active .icon-svg svg[data-v-6f5fc07f]{filter:drop-shadow(0 2px 4px rgba(102,126,234,.3))}.tab-content[data-v-6f5fc07f]{flex:1}.tab-title[data-v-6f5fc07f]{font-weight:600;color:#2d3748;margin-bottom:.25rem;font-size:.9rem}.tab-description[data-v-6f5fc07f]{font-size:.75rem;color:#718096;line-height:1.3}.tab-indicator[data-v-6f5fc07f]{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);width:4px;height:20px;background:#667eea;border-radius:2px;opacity:0;transition:opacity .3s ease}.tab-item.active .tab-indicator[data-v-6f5fc07f]{opacity:1}.status-card[data-v-6f5fc07f]{background:#fffc;border-radius:12px;padding:1rem;border:1px solid rgba(0,0,0,.05);margin-bottom:.75rem}.status-header[data-v-6f5fc07f]{display:flex;align-items:center;gap:.5rem;margin-bottom:.75rem}.status-icon[data-v-6f5fc07f]{font-size:1rem}.status-title[data-v-6f5fc07f]{font-weight:600;color:#2d3748;font-size:.85rem}.status-content[data-v-6f5fc07f]{display:flex;flex-direction:column;gap:.5rem}.status-item[data-v-6f5fc07f]{display:flex;justify-content:space-between;align-items:center}.status-label[data-v-6f5fc07f]{font-size:.75rem;color:#718096}.status-value[data-v-6f5fc07f]{font-size:.75rem;font-weight:600;color:#2d3748}.status-value.running[data-v-6f5fc07f]{color:#22c55e}.stats-card[data-v-6f5fc07f]{background:#fffc;border-radius:12px;padding:1rem;border:1px solid rgba(0,0,0,.05)}.stats-header[data-v-6f5fc07f]{display:flex;align-items:center;gap:.5rem;margin-bottom:.75rem}.stats-icon[data-v-6f5fc07f]{font-size:1rem}.stats-title[data-v-6f5fc07f]{font-weight:600;color:#2d3748;font-size:.85rem}.stats-grid[data-v-6f5fc07f]{display:grid;grid-template-columns:repeat(1,1fr);gap:.5rem}.stat-item[data-v-6f5fc07f]{display:flex;justify-content:space-between;align-items:center;padding:.5rem 0}.stat-value[data-v-6f5fc07f]{font-size:1.25rem;font-weight:700;color:#667eea}.stat-label[data-v-6f5fc07f]{font-size:.7rem;color:#718096;font-weight:500}.divider[data-v-6f5fc07f]{width:1px;background:linear-gradient(to bottom,transparent 0%,rgba(226,232,240,.8) 20%,rgba(226,232,240,.8) 80%,transparent 100%);margin:0}.content-area[data-v-6f5fc07f]{flex:1;background:#ffffffe6;border-radius:0 16px 16px 0;padding:2rem;box-shadow:0 4px 16px #0000000d;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);border-left:none;overflow-y:auto} diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/favicon.ico b/prompto-lab-app/SF-Chain/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/prompto-lab-app/SF-Chain/src/main/resources/static/favicon.ico differ diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/anthropic.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/anthropic.svg new file mode 100644 index 0000000..23266e3 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/anthropic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/deepseek.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/deepseek.svg new file mode 100644 index 0000000..6e2cac4 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/deepseek.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/default.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/default.svg new file mode 100644 index 0000000..f72b3a4 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/doubao.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/doubao.svg new file mode 100644 index 0000000..db0bca8 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/doubao.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/google.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/google.svg new file mode 100644 index 0000000..db14fba --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/openai.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/openai.svg new file mode 100644 index 0000000..d2a5a1e --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/openai.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/icons/qianwen.svg b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/qianwen.svg new file mode 100644 index 0000000..6bc8ba6 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/icons/qianwen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/prompto-lab-app/SF-Chain/src/main/resources/static/index.html b/prompto-lab-app/SF-Chain/src/main/resources/static/index.html new file mode 100644 index 0000000..f697a51 --- /dev/null +++ b/prompto-lab-app/SF-Chain/src/main/resources/static/index.html @@ -0,0 +1,16 @@ + + + + + + + Vite App + + + + + + +
+ + diff --git a/prompto-lab-app/pom.xml b/prompto-lab-app/pom.xml index a5ec5f2..2ce78c9 100644 --- a/prompto-lab-app/pom.xml +++ b/prompto-lab-app/pom.xml @@ -119,6 +119,13 @@ fastjson 2.0.57 + + + com.suifeng + sf-chain + 1.0.0 + + diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/model/PromptAI.java b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/model/PromptAI.java index ff6823c..9d91346 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/model/PromptAI.java +++ b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/model/PromptAI.java @@ -1,6 +1,6 @@ package io.github.timemachinelab.core.model; -import io.github.timemachinelab.sfchain.annotation.AIOp; +import com.suifeng.sfchain.annotation.AIOp; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/application/ConversationService.java b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/application/ConversationService.java index fde0a41..7c98b2a 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/application/ConversationService.java +++ b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/application/ConversationService.java @@ -2,9 +2,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.suifeng.sfchain.core.AIService; import io.github.timemachinelab.core.session.domain.entity.ConversationSession; import io.github.timemachinelab.core.session.infrastructure.ai.QuestionGenerationOperation; -import io.github.timemachinelab.sfchain.core.AIService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/ConversationOperation.java b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/ConversationOperation.java index bed5b31..4381229 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/ConversationOperation.java +++ b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/ConversationOperation.java @@ -1,7 +1,7 @@ package io.github.timemachinelab.core.session.infrastructure.ai; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.BaseAIOperation; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/QuestionGenerationOperation.java b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/QuestionGenerationOperation.java index 4a48c92..bc3d85f 100644 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/QuestionGenerationOperation.java +++ b/prompto-lab-app/src/main/java/io/github/timemachinelab/core/session/infrastructure/ai/QuestionGenerationOperation.java @@ -1,10 +1,10 @@ package io.github.timemachinelab.core.session.infrastructure.ai; +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.BaseAIOperation; import io.github.timemachinelab.core.question.BaseQuestion; import io.github.timemachinelab.core.question.QuestionParser; import io.github.timemachinelab.core.question.QuestionParseException; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; diff --git a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIHttpClient.java b/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIHttpClient.java deleted file mode 100644 index be43113..0000000 --- a/prompto-lab-app/src/main/java/io/github/timemachinelab/sfchain/core/openai/OpenAIHttpClient.java +++ /dev/null @@ -1,143 +0,0 @@ -package io.github.timemachinelab.sfchain.core.openai; - -import com.alibaba.fastjson2.JSON; -import lombok.extern.slf4j.Slf4j; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -/** - * 描述: OpenAI兼容的HTTP客户端 - * @author suifeng - * 日期: 2025/8/11 - */ -@Slf4j -public class OpenAIHttpClient { - - private final String baseUrl; - private final String apiKey; - private final Map defaultHeaders; - - public OpenAIHttpClient(String baseUrl, String apiKey) { - this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl; - this.apiKey = apiKey; - this.defaultHeaders = Map.of( - "Content-Type", "application/json", - "Authorization", "Bearer " + apiKey - ); - } - - public OpenAIHttpClient(String baseUrl, String apiKey, Map additionalHeaders) { - this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl; - this.apiKey = apiKey; - this.defaultHeaders = new HashMap<>(); - this.defaultHeaders.put("Content-Type", "application/json"); - this.defaultHeaders.put("Authorization", "Bearer " + apiKey); - if (additionalHeaders != null) { - this.defaultHeaders.putAll(additionalHeaders); - } - } - - /** - * 发送聊天完成请求 - */ - public OpenAIResponse chatCompletion(OpenAIRequest request) { - try { - // 智能构建endpoint,避免重复的/v1路径 - String endpoint; - if (baseUrl.endsWith("/v1") || baseUrl.contains("/v1/")) { - // baseUrl已包含v1路径,直接添加chat/completions - endpoint = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "chat/completions"; - } else { - // baseUrl不包含v1路径,添加完整路径 - endpoint = baseUrl + "/v1/chat/completions"; - } - String requestBody = JSON.toJSONString(request); - - log.debug("发送请求到: {}", endpoint); - log.debug("请求体: {}", requestBody); - log.info("构建的API端点: {}", endpoint); - - HttpURLConnection connection = createConnection(endpoint); - - // 发送请求体 - try (OutputStream os = connection.getOutputStream()) { - byte[] input = requestBody.getBytes(StandardCharsets.UTF_8); - os.write(input, 0, input.length); - } - - // 读取响应 - StringBuilder response = new StringBuilder(); - int responseCode = connection.getResponseCode(); - - if (responseCode == HttpURLConnection.HTTP_OK) { - try (BufferedReader br = new BufferedReader( - new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = br.readLine()) != null) { - response.append(line); - } - } - } else { - // 读取错误响应 - try (BufferedReader br = new BufferedReader( - new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = br.readLine()) != null) { - response.append(line); - } - } - throw new RuntimeException("HTTP请求失败,状态码: " + responseCode + ", 响应: " + response.toString()); - } - - String responseBody = response.toString(); - log.debug("响应体: {}", responseBody); - - return JSON.parseObject(responseBody, OpenAIResponse.class); - - } catch (Exception e) { - log.error("OpenAI API调用失败", e); - throw new RuntimeException("OpenAI API调用失败: " + e.getMessage(), e); - } - } - - /** - * 创建HTTP连接 - */ - private HttpURLConnection createConnection(String endpoint) throws Exception { - URL url = new URL(endpoint); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - - connection.setRequestMethod("POST"); - connection.setDoOutput(true); - connection.setConnectTimeout(30000); // 30秒连接超时 - connection.setReadTimeout(120000); // 120秒读取超时 - - // 设置请求头 - defaultHeaders.forEach(connection::setRequestProperty); - - return connection; - } - - /** - * 提取响应内容 - */ - public String extractContent(OpenAIResponse response) { - if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) { - return ""; - } - - OpenAIResponse.Choice choice = response.getChoices().get(0); - if (choice.getMessage() != null && choice.getMessage().getContent() != null) { - return choice.getMessage().getContent(); - } - - return ""; - } -} \ No newline at end of file diff --git a/prompto-lab-app/src/main/resources/application.yml b/prompto-lab-app/src/main/resources/application.yml index 64ee53e..c4a9f5f 100644 --- a/prompto-lab-app/src/main/resources/application.yml +++ b/prompto-lab-app/src/main/resources/application.yml @@ -45,3 +45,14 @@ spring: open-in-view: false +# =========================================== +# SF-Chain AI框架配置 +# =========================================== +sf-chain: + # 授权配置 + auth-token: "suifeng666" # 授权Token(生产环境请修改) + authEnabled: true + persistence: + database-type: postgresql # 数据库类型 + + diff --git a/prompto-lab-app/src/test/java/io/github/timemachinelab/testnode/ainode/AIChatOperation.java b/prompto-lab-app/src/test/java/io/github/timemachinelab/testnode/ainode/AIChatOperation.java index de7a4b6..716fdd4 100644 --- a/prompto-lab-app/src/test/java/io/github/timemachinelab/testnode/ainode/AIChatOperation.java +++ b/prompto-lab-app/src/test/java/io/github/timemachinelab/testnode/ainode/AIChatOperation.java @@ -1,7 +1,8 @@ package io.github.timemachinelab.testnode.ainode; -import io.github.timemachinelab.sfchain.annotation.AIOp; -import io.github.timemachinelab.sfchain.core.BaseAIOperation; + +import com.suifeng.sfchain.annotation.AIOp; +import com.suifeng.sfchain.core.BaseAIOperation; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/prompto-lab-ui/src/components/layout/AppHeader.vue b/prompto-lab-ui/src/components/layout/AppHeader.vue index e7f685e..522d32a 100644 --- a/prompto-lab-ui/src/components/layout/AppHeader.vue +++ b/prompto-lab-ui/src/components/layout/AppHeader.vue @@ -143,15 +143,6 @@ onUnmounted(() => { - - - - diff --git a/prompto-lab-ui/src/router/index.ts b/prompto-lab-ui/src/router/index.ts index 439feeb..dc0d652 100644 --- a/prompto-lab-ui/src/router/index.ts +++ b/prompto-lab-ui/src/router/index.ts @@ -24,23 +24,7 @@ const router = createRouter({ meta: { title: 'AI构建器 - PromptoLab' } - }, - { - path: '/settings', - name: 'settings', - component: () => import('../views/SettingsView.vue'), - meta: { - title: '系统设置 - AI诗人' - } - }, - { - path: '/settings/api-config', - name: 'api-config', - component: () => import('../views/ApiConfigView.vue'), - meta: { - title: 'API配置 - AI诗人' - } - }, + } ] }) diff --git a/prompto-lab-ui/src/views/ApiConfigView.vue b/prompto-lab-ui/src/views/ApiConfigView.vue deleted file mode 100644 index d835e77..0000000 --- a/prompto-lab-ui/src/views/ApiConfigView.vue +++ /dev/null @@ -1,898 +0,0 @@ - - - - - diff --git a/prompto-lab-ui/src/views/SettingsView.vue b/prompto-lab-ui/src/views/SettingsView.vue deleted file mode 100644 index 9ba1e90..0000000 --- a/prompto-lab-ui/src/views/SettingsView.vue +++ /dev/null @@ -1,731 +0,0 @@ - - - - -