mirror of
https://github.com/wahyd4/links.git
synced 2026-08-08 21:04:53 +10:00
- Use a thinking/running face while speech audio is being generated - Switch to speaking only when playback actually begins - Add quota-safe history persistence that strips audio from older entries instead of crashing localStorage writes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
19 lines
76 KiB
JavaScript
19 lines
76 KiB
JavaScript
import{r as l,j as i,c as dn}from"./client-DS0SU7Jy.js";/**
|
||
* react-router v7.15.1
|
||
*
|
||
* Copyright (c) Remix Software Inc.
|
||
*
|
||
* This source code is licensed under the MIT license found in the
|
||
* LICENSE.md file in the root directory of this source tree.
|
||
*
|
||
* @license MIT
|
||
*/var Et="popstate";function Rt(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function hn(e={}){function t(r,a){var u;let s=(u=a.state)==null?void 0:u.masked,{pathname:o,search:c,hash:d}=s||r.location;return et("",{pathname:o,search:c,hash:d},a.state&&a.state.usr||null,a.state&&a.state.key||"default",s?{pathname:r.location.pathname,search:r.location.search,hash:r.location.hash}:void 0)}function n(r,a){return typeof a=="string"?a:Re(a)}return mn(t,n,null,e)}function M(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function q(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function fn(){return Math.random().toString(36).substring(2,10)}function kt(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function et(e,t,n=null,r,a){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?he(t):t,state:n,key:t&&t.key||r||fn(),mask:a}}function Re({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function he(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function mn(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:s=!1}=r,o=a.history,c="POP",d=null,u=f();u==null&&(u=0,o.replaceState({...o.state,idx:u},""));function f(){return(o.state||{idx:null}).idx}function h(){c="POP";let m=f(),g=m==null?null:m-u;u=m,d&&d({action:c,location:v.location,delta:g})}function p(m,g){c="PUSH";let x=Rt(m)?m:et(v.location,m,g);u=f()+1;let w=kt(x,u),$=v.createHref(x.mask||x);try{o.pushState(w,"",$)}catch(R){if(R instanceof DOMException&&R.name==="DataCloneError")throw R;a.location.assign($)}s&&d&&d({action:c,location:v.location,delta:1})}function b(m,g){c="REPLACE";let x=Rt(m)?m:et(v.location,m,g);u=f();let w=kt(x,u),$=v.createHref(x.mask||x);o.replaceState(w,"",$),s&&d&&d({action:c,location:v.location,delta:0})}function y(m){return pn(m)}let v={get action(){return c},get location(){return e(a,o)},listen(m){if(d)throw new Error("A history only accepts one active listener");return a.addEventListener(Et,h),d=m,()=>{a.removeEventListener(Et,h),d=null}},createHref(m){return t(a,m)},createURL:y,encodeLocation(m){let g=y(m);return{pathname:g.pathname,search:g.search,hash:g.hash}},push:p,replace:b,go(m){return o.go(m)}};return v}function pn(e,t=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),M(n,"No window.location.(origin|href) available to create URL");let r=typeof e=="string"?e:Re(e);return r=r.replace(/ $/,"%20"),!t&&r.startsWith("//")&&(r=n+r),new URL(r,n)}function Bt(e,t,n="/"){return gn(e,t,n,!1)}function gn(e,t,n,r,a){let s=typeof t=="string"?he(t):t,o=te(s.pathname||"/",n);if(o==null)return null;let c=yn(e),d=null,u=Tn(o);for(let f=0;d==null&&f<c.length;++f)d=Nn(c[f],u,r);return d}function yn(e){let t=Ft(e);return bn(t),t}function Ft(e,t=[],n=[],r="",a=!1){let s=(o,c,d=a,u)=>{let f={relativePath:u===void 0?o.path||"":u,caseSensitive:o.caseSensitive===!0,childrenIndex:c,route:o};if(f.relativePath.startsWith("/")){if(!f.relativePath.startsWith(r)&&d)return;M(f.relativePath.startsWith(r),`Absolute route path "${f.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),f.relativePath=f.relativePath.slice(r.length)}let h=W([r,f.relativePath]),p=n.concat(f);o.children&&o.children.length>0&&(M(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${h}".`),Ft(o.children,t,p,h,d)),!(o.path==null&&!o.index)&&t.push({path:h,score:Sn(h,o.index),routesMeta:p})};return e.forEach((o,c)=>{var d;if(o.path===""||!((d=o.path)!=null&&d.includes("?")))s(o,c);else for(let u of Ot(o.path))s(o,c,!0,u)}),t}function Ot(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,a=n.endsWith("?"),s=n.replace(/\?$/,"");if(r.length===0)return a?[s,""]:[s];let o=Ot(r.join("/")),c=[];return c.push(...o.map(d=>d===""?s:[s,d].join("/"))),a&&c.push(...o),c.map(d=>e.startsWith("/")&&d===""?"/":d)}function bn(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:jn(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var vn=/^:[\w-]+$/,wn=3,xn=2,En=1,Rn=10,kn=-2,St=e=>e==="*";function Sn(e,t){let n=e.split("/"),r=n.length;return n.some(St)&&(r+=kn),t&&(r+=xn),n.filter(a=>!St(a)).reduce((a,s)=>a+(vn.test(s)?wn:s===""?En:Rn),r)}function jn(e,t){return e.length===t.length&&e.slice(0,-1).every((r,a)=>r===t[a])?e[e.length-1]-t[t.length-1]:0}function Nn(e,t,n=!1){let{routesMeta:r}=e,a={},s="/",o=[];for(let c=0;c<r.length;++c){let d=r[c],u=c===r.length-1,f=s==="/"?t:t.slice(s.length)||"/",h=De({path:d.relativePath,caseSensitive:d.caseSensitive,end:u},f),p=d.route;if(!h&&u&&n&&!r[r.length-1].route.index&&(h=De({path:d.relativePath,caseSensitive:d.caseSensitive,end:!1},f)),!h)return null;Object.assign(a,h.params),o.push({params:a,pathname:W([s,h.pathname]),pathnameBase:_n(W([s,h.pathnameBase])),route:p}),h.pathnameBase!=="/"&&(s=W([s,h.pathnameBase]))}return o}function De(e,t){typeof e=="string"&&(e={path:e,caseSensitive:!1,end:!0});let[n,r]=Cn(e.path,e.caseSensitive,e.end),a=t.match(n);if(!a)return null;let s=a[0],o=s.replace(/(.)\/+$/,"$1"),c=a.slice(1);return{params:r.reduce((u,{paramName:f,isOptional:h},p)=>{if(f==="*"){let y=c[p]||"";o=s.slice(0,s.length-y.length).replace(/(.)\/+$/,"$1")}const b=c[p];return h&&!b?u[f]=void 0:u[f]=(b||"").replace(/%2F/g,"/"),u},{}),pathname:s,pathnameBase:o,pattern:e}}function Cn(e,t=!1,n=!0){q(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(o,c,d,u,f)=>{if(r.push({paramName:c,isOptional:d!=null}),d){let h=f.charAt(u+o.length);return h&&h!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(r.push({paramName:"*"}),a+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":e!==""&&e!=="/"&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function Tn(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return q(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function te(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}var Mn=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function An(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?he(e):e,s;return n?(n=Ut(n),n.startsWith("/")?s=jt(n.substring(1),"/"):s=jt(n,t)):s=t,{pathname:s,search:In(r),hash:Pn(a)}}function jt(e,t){let n=Ue(t).split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Ye(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function $n(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Dt(e){let t=$n(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function ot(e,t,n,r=!1){let a;typeof e=="string"?a=he(e):(a={...e},M(!a.pathname||!a.pathname.includes("?"),Ye("?","pathname","search",a)),M(!a.pathname||!a.pathname.includes("#"),Ye("#","pathname","hash",a)),M(!a.search||!a.search.includes("#"),Ye("#","search","hash",a)));let s=e===""||a.pathname==="",o=s?"/":a.pathname,c;if(o==null)c=n;else{let h=t.length-1;if(!r&&o.startsWith("..")){let p=o.split("/");for(;p[0]==="..";)p.shift(),h-=1;a.pathname=p.join("/")}c=h>=0?t[h]:"/"}let d=An(a,c),u=o&&o!=="/"&&o.endsWith("/"),f=(s||o===".")&&n.endsWith("/");return!d.pathname.endsWith("/")&&(u||f)&&(d.pathname+="/"),d}var Ut=e=>e.replace(/\/\/+/g,"/"),W=e=>Ut(e.join("/")),Ue=e=>e.replace(/\/+$/,""),_n=e=>Ue(e).replace(/^\/*/,"/"),In=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Pn=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,Ln=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||"",this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function Bn(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function Fn(e){let t=e.map(n=>n.route.path).filter(Boolean);return W(t)||"/"}var Ht=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function zt(e,t){let n=e;if(typeof n!="string"||!Mn.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,a=!1;if(Ht)try{let s=new URL(window.location.href),o=n.startsWith("//")?new URL(s.protocol+n):new URL(n),c=te(o.pathname,t);o.origin===s.origin&&c!=null?n=c+o.search+o.hash:a=!0}catch{q(!1,`<Link to="${n}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:a,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Wt=["POST","PUT","PATCH","DELETE"];new Set(Wt);var On=["GET",...Wt];new Set(On);var fe=l.createContext(null);fe.displayName="DataRouter";var ze=l.createContext(null);ze.displayName="DataRouterState";var Vt=l.createContext(!1);function Dn(){return l.useContext(Vt)}var Kt=l.createContext({isTransitioning:!1});Kt.displayName="ViewTransition";var Un=l.createContext(new Map);Un.displayName="Fetchers";var Hn=l.createContext(null);Hn.displayName="Await";var z=l.createContext(null);z.displayName="Navigation";var Se=l.createContext(null);Se.displayName="Location";var ne=l.createContext({outlet:null,matches:[],isDataRoute:!1});ne.displayName="Route";var it=l.createContext(null);it.displayName="RouteError";var Jt="REACT_ROUTER_ERROR",zn="REDIRECT",Wn="ROUTE_ERROR_RESPONSE";function Vn(e){if(e.startsWith(`${Jt}:${zn}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.location=="string"&&typeof t.reloadDocument=="boolean"&&typeof t.replace=="boolean")return t}catch{}}function Kn(e){if(e.startsWith(`${Jt}:${Wn}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new Ln(t.status,t.statusText,t.data)}catch{}}function Jn(e,{relative:t}={}){M(je(),"useHref() may be used only in the context of a <Router> component.");let{basename:n,navigator:r}=l.useContext(z),{hash:a,pathname:s,search:o}=Ce(e,{relative:t}),c=s;return n!=="/"&&(c=s==="/"?n:W([n,s])),r.createHref({pathname:c,search:o,hash:a})}function je(){return l.useContext(Se)!=null}function re(){return M(je(),"useLocation() may be used only in the context of a <Router> component."),l.useContext(Se).location}var qt="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Gt(e){l.useContext(z).static||l.useLayoutEffect(e)}function Ne(){let{isDataRoute:e}=l.useContext(ne);return e?or():qn()}function qn(){M(je(),"useNavigate() may be used only in the context of a <Router> component.");let e=l.useContext(fe),{basename:t,navigator:n}=l.useContext(z),{matches:r}=l.useContext(ne),{pathname:a}=re(),s=JSON.stringify(Dt(r)),o=l.useRef(!1);return Gt(()=>{o.current=!0}),l.useCallback((d,u={})=>{if(q(o.current,qt),!o.current)return;if(typeof d=="number"){n.go(d);return}let f=ot(d,JSON.parse(s),a,u.relative==="path");e==null&&t!=="/"&&(f.pathname=f.pathname==="/"?t:W([t,f.pathname])),(u.replace?n.replace:n.push)(f,u.state,u)},[t,n,s,a,e])}l.createContext(null);function Ce(e,{relative:t}={}){let{matches:n}=l.useContext(ne),{pathname:r}=re(),a=JSON.stringify(Dt(n));return l.useMemo(()=>ot(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Gn(e,t){return Yt(e,t)}function Yt(e,t,n){var m;M(je(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:r}=l.useContext(z),{matches:a}=l.useContext(ne),s=a[a.length-1],o=s?s.params:{},c=s?s.pathname:"/",d=s?s.pathnameBase:"/",u=s&&s.route;{let g=u&&u.path||"";Qt(c,!u||g.endsWith("*")||g.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${c}" (under <Route path="${g}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
|
||
|
||
Please change the parent <Route path="${g}"> to <Route path="${g==="/"?"*":`${g}/*`}">.`)}let f=re(),h;if(t){let g=typeof t=="string"?he(t):t;M(d==="/"||((m=g.pathname)==null?void 0:m.startsWith(d)),`When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${d}" but pathname "${g.pathname}" was given in the \`location\` prop.`),h=g}else h=f;let p=h.pathname||"/",b=p;if(d!=="/"){let g=d.replace(/^\//,"").split("/");b="/"+p.replace(/^\//,"").split("/").slice(g.length).join("/")}let y=n&&n.state.matches.length?n.state.matches.map(g=>Object.assign(g,{route:n.manifest[g.route.id]||g.route})):Bt(e,{pathname:b});q(u||y!=null,`No routes matched location "${h.pathname}${h.search}${h.hash}" `),q(y==null||y[y.length-1].route.element!==void 0||y[y.length-1].route.Component!==void 0||y[y.length-1].route.lazy!==void 0,`Matched leaf route at location "${h.pathname}${h.search}${h.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`);let v=er(y&&y.map(g=>Object.assign({},g,{params:Object.assign({},o,g.params),pathname:W([d,r.encodeLocation?r.encodeLocation(g.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathname]),pathnameBase:g.pathnameBase==="/"?d:W([d,r.encodeLocation?r.encodeLocation(g.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathnameBase])})),a,n);return t&&v?l.createElement(Se.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",mask:void 0,...h},navigationType:"POP"}},v):v}function Yn(){let e=sr(),t=Bn(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r="rgba(200,200,200, 0.5)",a={padding:"0.5rem",backgroundColor:r},s={padding:"2px 4px",backgroundColor:r},o=null;return console.error("Error handled by React Router default ErrorBoundary:",e),o=l.createElement(l.Fragment,null,l.createElement("p",null,"💿 Hey developer 👋"),l.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",l.createElement("code",{style:s},"ErrorBoundary")," or"," ",l.createElement("code",{style:s},"errorElement")," prop on your route.")),l.createElement(l.Fragment,null,l.createElement("h2",null,"Unexpected Application Error!"),l.createElement("h3",{style:{fontStyle:"italic"}},t),n?l.createElement("pre",{style:a},n):null,o)}var Xn=l.createElement(Yn,null),Xt=class extends l.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error("React Router caught the following error during render",e)}render(){let e=this.state.error;if(this.context&&typeof e=="object"&&e&&"digest"in e&&typeof e.digest=="string"){const n=Kn(e.digest);n&&(e=n)}let t=e!==void 0?l.createElement(ne.Provider,{value:this.props.routeContext},l.createElement(it.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?l.createElement(Qn,{error:e},t):t}};Xt.contextType=Vt;var Xe=new WeakMap;function Qn({children:e,error:t}){let{basename:n}=l.useContext(z);if(typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){let r=Vn(t.digest);if(r){let a=Xe.get(t);if(a)throw a;let s=zt(r.location,n);if(Ht&&!Xe.get(t))if(s.isExternal||r.reloadDocument)window.location.href=s.absoluteURL||s.to;else{const o=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(s.to,{replace:r.replace}));throw Xe.set(t,o),o}return l.createElement("meta",{httpEquiv:"refresh",content:`0;url=${s.absoluteURL||s.to}`})}}return e}function Zn({routeContext:e,match:t,children:n}){let r=l.useContext(fe);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),l.createElement(ne.Provider,{value:e},n)}function er(e,t=[],n){let r=n==null?void 0:n.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let a=e,s=r==null?void 0:r.errors;if(s!=null){let f=a.findIndex(h=>h.route.id&&(s==null?void 0:s[h.route.id])!==void 0);M(f>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(s).join(",")}`),a=a.slice(0,Math.min(a.length,f+1))}let o=!1,c=-1;if(n&&r){o=r.renderFallback;for(let f=0;f<a.length;f++){let h=a[f];if((h.route.HydrateFallback||h.route.hydrateFallbackElement)&&(c=f),h.route.id){let{loaderData:p,errors:b}=r,y=h.route.loader&&!p.hasOwnProperty(h.route.id)&&(!b||b[h.route.id]===void 0);if(h.route.lazy||y){n.isStatic&&(o=!0),c>=0?a=a.slice(0,c+1):a=[a[0]];break}}}}let d=n==null?void 0:n.onError,u=r&&d?(f,h)=>{var p,b;d(f,{location:r.location,params:((b=(p=r.matches)==null?void 0:p[0])==null?void 0:b.params)??{},pattern:Fn(r.matches),errorInfo:h})}:void 0;return a.reduceRight((f,h,p)=>{let b,y=!1,v=null,m=null;r&&(b=s&&h.route.id?s[h.route.id]:void 0,v=h.route.errorElement||Xn,o&&(c<0&&p===0?(Qt("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),y=!0,m=null):c===p&&(y=!0,m=h.route.hydrateFallbackElement||null)));let g=t.concat(a.slice(0,p+1)),x=()=>{let w;return b?w=v:y?w=m:h.route.Component?w=l.createElement(h.route.Component,null):h.route.element?w=h.route.element:w=f,l.createElement(Zn,{match:h,routeContext:{outlet:f,matches:g,isDataRoute:r!=null},children:w})};return r&&(h.route.ErrorBoundary||h.route.errorElement||p===0)?l.createElement(Xt,{location:r.location,revalidation:r.revalidation,component:v,error:b,children:x(),routeContext:{outlet:null,matches:g,isDataRoute:!0},onError:u}):x()},null)}function lt(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function tr(e){let t=l.useContext(fe);return M(t,lt(e)),t}function nr(e){let t=l.useContext(ze);return M(t,lt(e)),t}function rr(e){let t=l.useContext(ne);return M(t,lt(e)),t}function ct(e){let t=rr(e),n=t.matches[t.matches.length-1];return M(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function ar(){return ct("useRouteId")}function sr(){var r;let e=l.useContext(it),t=nr("useRouteError"),n=ct("useRouteError");return e!==void 0?e:(r=t.errors)==null?void 0:r[n]}function or(){let{router:e}=tr("useNavigate"),t=ct("useNavigate"),n=l.useRef(!1);return Gt(()=>{n.current=!0}),l.useCallback(async(a,s={})=>{q(n.current,qt),n.current&&(typeof a=="number"?await e.navigate(a):await e.navigate(a,{fromRouteId:t,...s}))},[e,t])}var Nt={};function Qt(e,t,n){!t&&!Nt[e]&&(Nt[e]=!0,q(!1,n))}l.memo(ir);function ir({routes:e,manifest:t,future:n,state:r,isStatic:a,onError:s}){return Yt(e,void 0,{manifest:t,state:r,isStatic:a,onError:s})}function Be(e){M(!1,"A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.")}function lr({basename:e="/",children:t=null,location:n,navigationType:r="POP",navigator:a,static:s=!1,useTransitions:o}){M(!je(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let c=e.replace(/^\/*/,"/"),d=l.useMemo(()=>({basename:c,navigator:a,static:s,useTransitions:o,future:{}}),[c,a,s,o]);typeof n=="string"&&(n=he(n));let{pathname:u="/",search:f="",hash:h="",state:p=null,key:b="default",mask:y}=n,v=l.useMemo(()=>{let m=te(u,c);return m==null?null:{location:{pathname:m,search:f,hash:h,state:p,key:b,mask:y},navigationType:r}},[c,u,f,h,p,b,r,y]);return q(v!=null,`<Router basename="${c}"> is not able to match the URL "${u}${f}${h}" because it does not start with the basename, so the <Router> won't render anything.`),v==null?null:l.createElement(z.Provider,{value:d},l.createElement(Se.Provider,{children:t,value:v}))}function cr({children:e,location:t}){return Gn(tt(e),t)}function tt(e,t=[]){let n=[];return l.Children.forEach(e,(r,a)=>{if(!l.isValidElement(r))return;let s=[...t,a];if(r.type===l.Fragment){n.push.apply(n,tt(r.props.children,s));return}M(r.type===Be,`[${typeof r.type=="string"?r.type:r.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`),M(!r.props.index||!r.props.children,"An index route cannot have child routes.");let o={id:r.props.id||s.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,middleware:r.props.middleware,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(o.children=tt(r.props.children,s)),n.push(o)}),n}var Fe="get",Oe="application/x-www-form-urlencoded";function We(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function ur(e){return We(e)&&e.tagName.toLowerCase()==="button"}function dr(e){return We(e)&&e.tagName.toLowerCase()==="form"}function hr(e){return We(e)&&e.tagName.toLowerCase()==="input"}function fr(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function mr(e,t){return e.button===0&&(!t||t==="_self")&&!fr(e)}var _e=null;function pr(){if(_e===null)try{new FormData(document.createElement("form"),0),_e=!1}catch{_e=!0}return _e}var gr=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Qe(e){return e!=null&&!gr.has(e)?(q(!1,`"${e}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${Oe}"`),null):e}function yr(e,t){let n,r,a,s,o;if(dr(e)){let c=e.getAttribute("action");r=c?te(c,t):null,n=e.getAttribute("method")||Fe,a=Qe(e.getAttribute("enctype"))||Oe,s=new FormData(e)}else if(ur(e)||hr(e)&&(e.type==="submit"||e.type==="image")){let c=e.form;if(c==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let d=e.getAttribute("formaction")||c.getAttribute("action");if(r=d?te(d,t):null,n=e.getAttribute("formmethod")||c.getAttribute("method")||Fe,a=Qe(e.getAttribute("formenctype"))||Qe(c.getAttribute("enctype"))||Oe,s=new FormData(c,e),!pr()){let{name:u,type:f,value:h}=e;if(f==="image"){let p=u?`${u}.`:"";s.append(`${p}x`,"0"),s.append(`${p}y`,"0")}else u&&s.append(u,h)}}else{if(We(e))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');n=Fe,r=null,a=Oe,o=e}return s&&a==="text/plain"&&(o=s,s=void 0),{action:r,method:n.toLowerCase(),encType:a,formData:s,body:o}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function ut(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function Zt(e,t,n,r){let a=typeof e=="string"?new URL(e,typeof window>"u"?"server://singlefetch/":window.location.origin):e;return n?a.pathname.endsWith("/")?a.pathname=`${a.pathname}_.${r}`:a.pathname=`${a.pathname}.${r}`:a.pathname==="/"?a.pathname=`_root.${r}`:t&&te(a.pathname,t)==="/"?a.pathname=`${Ue(t)}/_root.${r}`:a.pathname=`${Ue(a.pathname)}.${r}`,a}async function br(e,t){if(e.id in t)return t[e.id];try{let n=await import(e.module);return t[e.id]=n,n}catch(n){return console.error(`Error loading route module \`${e.module}\`, reloading page...`),console.error(n),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function vr(e){return e==null?!1:e.href==null?e.rel==="preload"&&typeof e.imageSrcSet=="string"&&typeof e.imageSizes=="string":typeof e.rel=="string"&&typeof e.href=="string"}async function wr(e,t,n){let r=await Promise.all(e.map(async a=>{let s=t.routes[a.route.id];if(s){let o=await br(s,n);return o.links?o.links():[]}return[]}));return kr(r.flat(1).filter(vr).filter(a=>a.rel==="stylesheet"||a.rel==="preload").map(a=>a.rel==="stylesheet"?{...a,rel:"prefetch",as:"style"}:{...a,rel:"prefetch"}))}function Ct(e,t,n,r,a,s){let o=(d,u)=>n[u]?d.route.id!==n[u].route.id:!0,c=(d,u)=>{var f;return n[u].pathname!==d.pathname||((f=n[u].route.path)==null?void 0:f.endsWith("*"))&&n[u].params["*"]!==d.params["*"]};return s==="assets"?t.filter((d,u)=>o(d,u)||c(d,u)):s==="data"?t.filter((d,u)=>{var h;let f=r.routes[d.route.id];if(!f||!f.hasLoader)return!1;if(o(d,u)||c(d,u))return!0;if(d.route.shouldRevalidate){let p=d.route.shouldRevalidate({currentUrl:new URL(a.pathname+a.search+a.hash,window.origin),currentParams:((h=n[0])==null?void 0:h.params)||{},nextUrl:new URL(e,window.origin),nextParams:d.params,defaultShouldRevalidate:!0});if(typeof p=="boolean")return p}return!0}):[]}function xr(e,t,{includeHydrateFallback:n}={}){return Er(e.map(r=>{let a=t.routes[r.route.id];if(!a)return[];let s=[a.module];return a.clientActionModule&&(s=s.concat(a.clientActionModule)),a.clientLoaderModule&&(s=s.concat(a.clientLoaderModule)),n&&a.hydrateFallbackModule&&(s=s.concat(a.hydrateFallbackModule)),a.imports&&(s=s.concat(a.imports)),s}).flat(1))}function Er(e){return[...new Set(e)]}function Rr(e){let t={},n=Object.keys(e).sort();for(let r of n)t[r]=e[r];return t}function kr(e,t){let n=new Set;return new Set(t),e.reduce((r,a)=>{let s=JSON.stringify(Rr(a));return n.has(s)||(n.add(s),r.push({key:s,link:a})),r},[])}function dt(){let e=l.useContext(fe);return ut(e,"You must render this element inside a <DataRouterContext.Provider> element"),e}function Sr(){let e=l.useContext(ze);return ut(e,"You must render this element inside a <DataRouterStateContext.Provider> element"),e}var ht=l.createContext(void 0);ht.displayName="FrameworkContext";function ft(){let e=l.useContext(ht);return ut(e,"You must render this element inside a <HydratedRouter> element"),e}function jr(e,t){let n=l.useContext(ht),[r,a]=l.useState(!1),[s,o]=l.useState(!1),{onFocus:c,onBlur:d,onMouseEnter:u,onMouseLeave:f,onTouchStart:h}=t,p=l.useRef(null);l.useEffect(()=>{if(e==="render"&&o(!0),e==="viewport"){let v=g=>{g.forEach(x=>{o(x.isIntersecting)})},m=new IntersectionObserver(v,{threshold:.5});return p.current&&m.observe(p.current),()=>{m.disconnect()}}},[e]),l.useEffect(()=>{if(r){let v=setTimeout(()=>{o(!0)},100);return()=>{clearTimeout(v)}}},[r]);let b=()=>{a(!0)},y=()=>{a(!1),o(!1)};return n?e!=="intent"?[s,p,{}]:[s,p,{onFocus:ye(c,b),onBlur:ye(d,y),onMouseEnter:ye(u,b),onMouseLeave:ye(f,y),onTouchStart:ye(h,b)}]:[!1,p,{}]}function ye(e,t){return n=>{e&&e(n),n.defaultPrevented||t(n)}}function Nr({page:e,...t}){let n=Dn(),{router:r}=dt(),a=l.useMemo(()=>Bt(r.routes,e,r.basename),[r.routes,e,r.basename]);return a?n?l.createElement(Tr,{page:e,matches:a,...t}):l.createElement(Mr,{page:e,matches:a,...t}):null}function Cr(e){let{manifest:t,routeModules:n}=ft(),[r,a]=l.useState([]);return l.useEffect(()=>{let s=!1;return wr(e,t,n).then(o=>{s||a(o)}),()=>{s=!0}},[e,t,n]),r}function Tr({page:e,matches:t,...n}){let r=re(),{future:a}=ft(),{basename:s}=dt(),o=l.useMemo(()=>{if(e===r.pathname+r.search+r.hash)return[];let c=Zt(e,s,a.unstable_trailingSlashAwareDataRequests,"rsc"),d=!1,u=[];for(let f of t)typeof f.route.shouldRevalidate=="function"?d=!0:u.push(f.route.id);return d&&u.length>0&&c.searchParams.set("_routes",u.join(",")),[c.pathname+c.search]},[s,a.unstable_trailingSlashAwareDataRequests,e,r,t]);return l.createElement(l.Fragment,null,o.map(c=>l.createElement("link",{key:c,rel:"prefetch",as:"fetch",href:c,...n})))}function Mr({page:e,matches:t,...n}){let r=re(),{future:a,manifest:s,routeModules:o}=ft(),{basename:c}=dt(),{loaderData:d,matches:u}=Sr(),f=l.useMemo(()=>Ct(e,t,u,s,r,"data"),[e,t,u,s,r]),h=l.useMemo(()=>Ct(e,t,u,s,r,"assets"),[e,t,u,s,r]),p=l.useMemo(()=>{if(e===r.pathname+r.search+r.hash)return[];let v=new Set,m=!1;if(t.forEach(x=>{var $;let w=s.routes[x.route.id];!w||!w.hasLoader||(!f.some(R=>R.route.id===x.route.id)&&x.route.id in d&&(($=o[x.route.id])!=null&&$.shouldRevalidate)||w.hasClientLoader?m=!0:v.add(x.route.id))}),v.size===0)return[];let g=Zt(e,c,a.unstable_trailingSlashAwareDataRequests,"data");return m&&v.size>0&&g.searchParams.set("_routes",t.filter(x=>v.has(x.route.id)).map(x=>x.route.id).join(",")),[g.pathname+g.search]},[c,a.unstable_trailingSlashAwareDataRequests,d,r,s,f,t,e,o]),b=l.useMemo(()=>xr(h,s),[h,s]),y=Cr(h);return l.createElement(l.Fragment,null,p.map(v=>l.createElement("link",{key:v,rel:"prefetch",as:"fetch",href:v,...n})),b.map(v=>l.createElement("link",{key:v,rel:"modulepreload",href:v,...n})),y.map(({key:v,link:m})=>l.createElement("link",{key:v,nonce:n.nonce,...m,crossOrigin:m.crossOrigin??n.crossOrigin})))}function Ar(...e){return t=>{e.forEach(n=>{typeof n=="function"?n(t):n!=null&&(n.current=t)})}}var $r=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{$r&&(window.__reactRouterVersion="7.15.1")}catch{}function _r({basename:e,children:t,useTransitions:n,window:r}){let a=l.useRef();a.current==null&&(a.current=hn({window:r,v5Compat:!0}));let s=a.current,[o,c]=l.useState({action:s.action,location:s.location}),d=l.useCallback(u=>{n===!1?c(u):l.startTransition(()=>c(u))},[n]);return l.useLayoutEffect(()=>s.listen(d),[s,d]),l.createElement(lr,{basename:e,children:t,location:o.location,navigationType:o.action,navigator:s,useTransitions:n})}var en=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,tn=l.forwardRef(function({onClick:t,discover:n="render",prefetch:r="none",relative:a,reloadDocument:s,replace:o,mask:c,state:d,target:u,to:f,preventScrollReset:h,viewTransition:p,defaultShouldRevalidate:b,...y},v){let{basename:m,navigator:g,useTransitions:x}=l.useContext(z),w=typeof f=="string"&&en.test(f),$=zt(f,m);f=$.to;let R=Jn(f,{relative:a}),U=re(),V=null;if(c){let I=ot(c,[],U.mask?U.mask.pathname:"/",!0);m!=="/"&&(I.pathname=I.pathname==="/"?m:W([m,I.pathname])),V=g.createHref(I)}let[X,ie,me]=jr(r,y),Ke=Br(f,{replace:o,mask:c,state:d,target:u,preventScrollReset:h,relative:a,viewTransition:p,defaultShouldRevalidate:b,useTransitions:x});function le(I){t&&t(I),I.defaultPrevented||Ke(I)}let Te=!($.isExternal||s),Q=l.createElement("a",{...y,...me,href:(Te?V:void 0)||$.absoluteURL||R,onClick:Te?le:t,ref:Ar(v,ie),target:u,"data-discover":!w&&n==="render"?"true":void 0});return X&&!w?l.createElement(l.Fragment,null,Q,l.createElement(Nr,{page:R})):Q});tn.displayName="Link";var Ir=l.forwardRef(function({"aria-current":t="page",caseSensitive:n=!1,className:r="",end:a=!1,style:s,to:o,viewTransition:c,children:d,...u},f){let h=Ce(o,{relative:u.relative}),p=re(),b=l.useContext(ze),{navigator:y,basename:v}=l.useContext(z),m=b!=null&&Hr(h)&&c===!0,g=y.encodeLocation?y.encodeLocation(h).pathname:h.pathname,x=p.pathname,w=b&&b.navigation&&b.navigation.location?b.navigation.location.pathname:null;n||(x=x.toLowerCase(),w=w?w.toLowerCase():null,g=g.toLowerCase()),w&&v&&(w=te(w,v)||w);const $=g!=="/"&&g.endsWith("/")?g.length-1:g.length;let R=x===g||!a&&x.startsWith(g)&&x.charAt($)==="/",U=w!=null&&(w===g||!a&&w.startsWith(g)&&w.charAt(g.length)==="/"),V={isActive:R,isPending:U,isTransitioning:m},X=R?t:void 0,ie;typeof r=="function"?ie=r(V):ie=[r,R?"active":null,U?"pending":null,m?"transitioning":null].filter(Boolean).join(" ");let me=typeof s=="function"?s(V):s;return l.createElement(tn,{...u,"aria-current":X,className:ie,ref:f,style:me,to:o,viewTransition:c},typeof d=="function"?d(V):d)});Ir.displayName="NavLink";var Pr=l.forwardRef(({discover:e="render",fetcherKey:t,navigate:n,reloadDocument:r,replace:a,state:s,method:o=Fe,action:c,onSubmit:d,relative:u,preventScrollReset:f,viewTransition:h,defaultShouldRevalidate:p,...b},y)=>{let{useTransitions:v}=l.useContext(z),m=Dr(),g=Ur(c,{relative:u}),x=o.toLowerCase()==="get"?"get":"post",w=typeof c=="string"&&en.test(c),$=R=>{if(d&&d(R),R.defaultPrevented)return;R.preventDefault();let U=R.nativeEvent.submitter,V=(U==null?void 0:U.getAttribute("formmethod"))||o,X=()=>m(U||R.currentTarget,{fetcherKey:t,method:V,navigate:n,replace:a,state:s,relative:u,preventScrollReset:f,viewTransition:h,defaultShouldRevalidate:p});v&&n!==!1?l.startTransition(()=>X()):X()};return l.createElement("form",{ref:y,method:x,action:g,onSubmit:r?d:$,...b,"data-discover":!w&&e==="render"?"true":void 0})});Pr.displayName="Form";function Lr(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function nn(e){let t=l.useContext(fe);return M(t,Lr(e)),t}function Br(e,{target:t,replace:n,mask:r,state:a,preventScrollReset:s,relative:o,viewTransition:c,defaultShouldRevalidate:d,useTransitions:u}={}){let f=Ne(),h=re(),p=Ce(e,{relative:o});return l.useCallback(b=>{if(mr(b,t)){b.preventDefault();let y=n!==void 0?n:Re(h)===Re(p),v=()=>f(e,{replace:y,mask:r,state:a,preventScrollReset:s,relative:o,viewTransition:c,defaultShouldRevalidate:d});u?l.startTransition(()=>v()):v()}},[h,f,p,n,r,a,t,e,s,o,c,d,u])}var Fr=0,Or=()=>`__${String(++Fr)}__`;function Dr(){let{router:e}=nn("useSubmit"),{basename:t}=l.useContext(z),n=ar(),r=e.fetch,a=e.navigate;return l.useCallback(async(s,o={})=>{let{action:c,method:d,encType:u,formData:f,body:h}=yr(s,t);if(o.navigate===!1){let p=o.fetcherKey||Or();await r(p,n,o.action||c,{defaultShouldRevalidate:o.defaultShouldRevalidate,preventScrollReset:o.preventScrollReset,formData:f,body:h,formMethod:o.method||d,formEncType:o.encType||u,flushSync:o.flushSync})}else await a(o.action||c,{defaultShouldRevalidate:o.defaultShouldRevalidate,preventScrollReset:o.preventScrollReset,formData:f,body:h,formMethod:o.method||d,formEncType:o.encType||u,replace:o.replace,state:o.state,fromRouteId:n,flushSync:o.flushSync,viewTransition:o.viewTransition})},[r,a,t,n])}function Ur(e,{relative:t}={}){let{basename:n}=l.useContext(z),r=l.useContext(ne);M(r,"useFormAction must be used inside a RouteContext");let[a]=r.matches.slice(-1),s={...Ce(e||".",{relative:t})},o=re();if(e==null){s.search=o.search;let c=new URLSearchParams(s.search),d=c.getAll("index");if(d.some(f=>f==="")){c.delete("index"),d.filter(h=>h).forEach(h=>c.append("index",h));let f=c.toString();s.search=f?`?${f}`:""}}return(!e||e===".")&&a.route.index&&(s.search=s.search?s.search.replace(/^\?/,"?index&"):"?index"),n!=="/"&&(s.pathname=s.pathname==="/"?n:W([n,s.pathname])),Re(s)}function Hr(e,{relative:t}={}){let n=l.useContext(Kt);M(n!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:r}=nn("useViewTransitionState"),a=Ce(e,{relative:t});if(!n.isTransitioning)return!1;let s=te(n.currentLocation.pathname,r)||n.currentLocation.pathname,o=te(n.nextLocation.pathname,r)||n.nextLocation.pathname;return De(a.pathname,o)!=null||De(a.pathname,s)!=null}const L=6,se=2.6,J=240,Z={LE:[10,13],RE:[29,13],MO:[20,27]};function G(e,t,n){const r=[],a=Math.ceil(n);for(let s=-a;s<=a;s++)for(let o=-a;o<=a;o++)s*s+o*o<=n*n&&r.push([e+s,t+o]);return r}function F(e,t,n,r,a,s=5){const o=[],c=new Set;for(let d=r;d<=a;d+=s){const u=d*Math.PI/180,f=Math.round(e+n*Math.cos(u)),h=Math.round(t+n*Math.sin(u)),p=`${f},${h}`;c.has(p)||(c.add(p),o.push([f,h]))}return o}function Y(e,t,n){const r=[];for(let a=Math.round(e-n);a<=Math.round(e+n);a++)r.push([a,Math.round(t)]);return r}function nt(e,t,n,r){const a=[],s=new Set,o=Math.round(n);for(let c=-o;c<=o;c++){const d=c/o*Math.PI,u=Math.round(t+r*Math.sin(d)),f=`${e+c},${u}`;s.has(f)||(s.add(f),a.push([e+c,u]))}return a}function zr(e,t,n,r){const a=[],s=Math.round(n);for(let o=-s;o<=s;o++){const c=o+s;a.push([e+o,Math.round(t+(c%4<2?r:-r))])}return a}function Tt(e,t){return[[-1,-2],[1,-2],[-2,-1],[-1,-1],[0,-1],[1,-1],[2,-1],[-2,0],[-1,0],[0,0],[1,0],[2,0],[-1,1],[0,1],[1,1],[0,2]].map(([n,r])=>[e+n,t+r])}function Mt(e,t,n,r){const a=[],s=new Set,o=Math.round(r*2*Math.PI*8);for(let c=0;c<=o;c++){const d=c/o*r*2*Math.PI,u=c/o*n,f=Math.round(e+u*Math.cos(d)),h=Math.round(t+u*Math.sin(d)),p=`${f},${h}`;s.has(p)||(s.add(p),a.push([f,h]))}return a}function Ze(e,t){return[[e-1,t-1],[e,t-1],[e+1,t-1],[e,t],[e-1,t+1],[e,t+1],[e+1,t+1]]}function At(e,t){return[...F(e,t-1,1.5,200,360,30),[e,t+1],[e,t+3]]}function ee(e,t){return{iris:G(e,t,3),pupil:G(e,t,1.5),hl:[[e-1,t-1]],lash:Y(e,t-3,3)}}function H(e,t){return{iris:G(e,t,4),pupil:G(e,t,2),hl:[[e-1,t-1],[e-2,t-2]],lash:Y(e,t-4,4)}}function de(e,t){return{iris:G(e,t,3).filter(([,r])=>r>=t-1&&r<=t+1),pupil:[[e,t]],lash:Y(e,t-1,2)}}function oe(e,t){return{iris:G(e,t,3).filter(([,r])=>r>=t),pupil:[[e-1,t],[e,t],[e+1,t]],lash:Y(e,t,3)}}function Ie(e,t){return{iris:G(e,t+1,3),pupil:G(e,t+2,1.5),hl:[[e-1,t]],lash:Y(e,t-2,2)}}function Pe(e,t,n=2){return{iris:G(e,t,3),pupil:G(e+n,t,1.5),hl:[[e+n-1,t-1]],lash:Y(e,t-3,3)}}function Wr(e,t){return{wink:F(e,t+1,3,200,340,15)}}function we(e,t){return F(e,t,5,25,155)}function rt(e,t){return F(e,t,7,15,165)}function $t(e,t){return Y(e,t,5)}function Vr(e,t){const n=F(e-2,t,4,30,120,10),r=F(e+3,t+2,2.5,270,360,15),a=new Set(n.map(([s,o])=>`${s},${o}`));return[...n,...r.filter(([s,o])=>!a.has(`${s},${o}`))]}function Kr(e,t){const n=F(e-2,t,2,200,340,20),r=F(e+2,t,2,200,340,20),a=Y(e,t+2,3),s=new Set(n.map(([o,c])=>`${o},${c}`));return[...n,...r.filter(([o,c])=>!s.has(`${o},${c}`)),...a]}function Jr(e,t,n){const r=Math.abs(Math.sin(n*1.4));if(r<.25)return F(e,t,4,20,160,8);const a=r<.65?1:2,s=F(e,t-a,3.5,190,350,8),o=F(e,t+a,3,10,170,8),c=new Set(s.map(([d,u])=>`${d},${u}`));return[...s,...o.filter(([d,u])=>!c.has(`${d},${u}`))]}const[k,S]=Z.LE,[j,N]=Z.RE,[C,T]=Z.MO,B="#22CCFF",qr=[{id:"idle",label:"😐 待机",color:"#00FFEE",category:"interaction",canBlink:!0,leftEye:ee(k,S),rightEye:ee(j,N),mouth:we(C,T)},{id:"listening",label:"👂 聆听",color:"#44AAFF",category:"interaction",canBlink:!0,leftEye:H(k,S),rightEye:H(j,N),mouth:F(C,T,3,0,180)},{id:"thinking",label:"🤔 思考",color:"#FFCC00",category:"interaction",canBlink:!0,leftEye:de(k,S),rightEye:ee(j,N),mouth:nt(C,T,5,1),extras:[{dots:At(k-1,S-6),color:"#FFCC00",alpha:.75}]},{id:"speaking",label:"💬 说话",color:"#FFFFFF",pupilColor:"#002233",category:"interaction",canBlink:!0,leftEye:ee(k,S),rightEye:ee(j,N),speakingMouth:!0},{id:"happy",label:"😊 开心",color:"#FF44AA",category:"interaction",canBlink:!0,leftEye:{heart:Tt(k,S)},rightEye:{heart:Tt(j,N)},mouth:rt(C,T)},{id:"error",label:"😵 错误",color:"#FF4400",category:"interaction",canBlink:!0,leftEye:{spiral:Mt(k,S,4,2)},rightEye:{spiral:Mt(j,N,4,2)},mouth:zr(C,T,5,1.5)},{id:"confused",label:"😕 困惑",color:"#BB44FF",category:"interaction",canBlink:!0,leftEye:H(k,S),rightEye:de(j,N),mouth:nt(C,T,5,1.5),extras:[{dots:At(j+1,N-6),color:"#BB44FF",alpha:.75}]},{id:"dreaming",label:"💤 做梦",color:"#5566FF",category:"interaction",canBlink:!0,leftEye:oe(k,S),rightEye:oe(j,N),mouth:we(C,T),extras:[{dots:Ze(24,10),color:"#5566FF",alpha:.85,zzzIndex:0},{dots:Ze(28,7),color:"#7788FF",alpha:.75,zzzIndex:1},{dots:Ze(32,4),color:"#99AAFF",alpha:.65,zzzIndex:2}]}],rn=[{id:"natural_smile",label:"01 自然微笑",color:B,category:"auto",canBlink:!0,leftEye:ee(k,S),rightEye:ee(j,N),mouth:we(C,T)},{id:"calm_relax",label:"02 平静放松",color:B,category:"auto",canBlink:!0,leftEye:oe(k,S),rightEye:oe(j,N),mouth:$t(C,T)},{id:"curious_observe",label:"03 好奇观察",color:B,category:"auto",canBlink:!0,leftEye:H(k,S),rightEye:H(j,N),mouth:F(C,T,4,30,150,8)},{id:"light_joy",label:"04 轻松愉悦",color:B,category:"auto",canBlink:!0,leftEye:de(k,S),rightEye:de(j,N),mouth:rt(C,T)},{id:"side_think",label:"05 侧目思考",color:B,category:"auto",canBlink:!0,leftEye:Pe(k,S,2),rightEye:Pe(j,N,2),mouth:nt(C,T,4,1)},{id:"warm_friendly",label:"06 温和友善",color:B,category:"auto",canBlink:!0,leftEye:Ie(k,S),rightEye:Ie(j,N),mouth:we(C,T)},{id:"quiet_listen",label:"07 静静聆听",color:B,category:"auto",canBlink:!0,leftEye:ee(k,S),rightEye:ee(j,N),mouth:Y(C,T,4)},{id:"focus_gaze",label:"08 专注注视",color:B,category:"auto",canBlink:!0,leftEye:H(k,S),rightEye:H(j,N),mouth:$t(C,T)},{id:"quiet_wait",label:"09 安静等待",color:B,category:"auto",canBlink:!0,leftEye:oe(k,S),rightEye:oe(j,N),mouth:F(C,T,4,30,150,8)},{id:"slow_blink",label:"10 慢眨眼",color:B,category:"auto",canBlink:!0,leftEye:de(k,S),rightEye:de(j,N),mouth:we(C,T)},{id:"look_around",label:"11 左右扫视",color:B,category:"auto",canBlink:!0,leftEye:Pe(k,S,-2),rightEye:Pe(j,N,-2),mouth:Y(C,T,4)},{id:"playful",label:"12 小小调皮",color:B,category:"auto",canBlink:!1,leftEye:Wr(k,S),rightEye:H(j,N),mouth:Vr(C,T)},{id:"joyful_wait",label:"13 愉悦期待",color:B,category:"auto",canBlink:!0,leftEye:H(k,S),rightEye:H(j,N),mouth:rt(C,T)},{id:"slight_surprise",label:"14 轻微惊喜",color:B,category:"auto",canBlink:!0,leftEye:H(k,S),rightEye:H(j,N),mouth:F(C,T,3,0,180,10)},{id:"gentle_gaze",label:"15 温柔注视",color:B,category:"auto",canBlink:!0,leftEye:Ie(k,S),rightEye:Ie(j,N),mouth:F(C,T,4,30,150,8)},{id:"spaceout",label:"16 发呆放空",color:B,category:"auto",canBlink:!0,leftEye:oe(k,S),rightEye:oe(j,N),mouth:Kr(C,T)}],mt=[...qr,...rn],be=rn.map(e=>e.id),at=Object.fromEntries(mt.map(e=>[e.id,e]));function D(e,t,n,r,a=null){if(!(!t||t.length===0)){if(e.save(),a==null){e.globalAlpha=Math.max(0,Math.min(1,r)),e.shadowBlur=14,e.shadowColor=n,e.fillStyle=n,e.beginPath();for(const[s,o]of t){const c=s*L+L/2,d=o*L+L/2;e.moveTo(c+se,d),e.arc(c,d,se,0,Math.PI*2)}e.fill(),e.shadowBlur=0,e.fillStyle="rgba(255,255,255,0.55)",e.beginPath();for(const[s,o]of t){const c=s*L+L/2,d=o*L+L/2;e.moveTo(c+se*.38,d),e.arc(c,d,se*.38,0,Math.PI*2)}e.fill()}else{const s=[],o=[];for(const[d,u]of t){const f=(d*7.3+u*13.1)*.31;(Math.sin(a*1.1+f)>0?s:o).push([d,u])}const c=(d,u,f)=>{if(d.length){e.globalAlpha=Math.max(0,Math.min(1,u)),e.shadowBlur=f,e.shadowColor=n,e.fillStyle=n,e.beginPath();for(const[h,p]of d){const b=h*L+L/2,y=p*L+L/2;e.moveTo(b+se,y),e.arc(b,y,se,0,Math.PI*2)}e.fill()}};c(o,r*.68,7),c(s,r,20),e.globalAlpha=Math.max(0,Math.min(1,r*.55)),e.shadowBlur=0,e.fillStyle="rgba(255,255,255,0.55)",e.beginPath();for(const[d,u]of t){const f=d*L+L/2,h=u*L+L/2;e.moveTo(f+se*.38,h),e.arc(f,h,se*.38,0,Math.PI*2)}e.fill()}e.restore()}}function ve(e,t,n){return n>=1?e:e.map(([r,a])=>[r,t+(a-t)*n])}function Gr(e,t){if(e===null)return 1;const n=t-e;return n<120?1-n/120:n<220?0:n<340?(n-220)/120:1}function _t(e,t,n,r,a,s,o,c,d){if(!t)return;const u=s||"#001020";t.iris?(D(e,ve(t.iris,r,c),a,o,d),D(e,ve(t.pupil,r,c),u,o,null),t.hl&&D(e,ve(t.hl,r,c),"#ffffff",o*.9,null),t.lash&&D(e,ve(t.lash,r,c),a,o,null)):t.closed!==void 0?(D(e,t.closed,a,o,d),t.lash&&D(e,t.lash,a,o,null)):t.wink?D(e,t.wink,a,o,d):t.heart?D(e,t.heart,a,o,d):t.spiral?D(e,t.spiral,a,o,d):t.star?D(e,t.star,a,o,d):t.pts&&D(e,ve(t.pts,r,c),a,o,d)}function Yr({expressionId:e,scale:t=2}){const n=l.useRef(null),r=l.useRef({currentId:e,previousId:null,transitionStart:null,blinkStart:null,nextBlink:performance.now()+2e3+Math.random()*2e3,t:0,raf:null});return l.useEffect(()=>{const a=r.current;e!==a.currentId&&(a.previousId=a.currentId,a.currentId=e,a.transitionStart=performance.now(),a.blinkStart=null)},[e]),l.useEffect(()=>{const s=n.current.getContext("2d"),o=r.current;function c(u,f,h,p){if(!u)return;_t(s,u.leftEye,Z.LE[0],Z.LE[1],u.color,u.pupilColor,f,h,p),_t(s,u.rightEye,Z.RE[0],Z.RE[1],u.color,u.pupilColor,f,h,p);const b=u.speakingMouth?Jr(Z.MO[0],Z.MO[1],o.t):u.mouth;if(b&&D(s,b,u.color,f,p),u.extras)for(const y of u.extras){let v=f*y.alpha;if(y.zzzIndex!==void 0){const m=o.t-y.zzzIndex*1.2;v*=.35+.65*(Math.sin(m)*.5+.5)}D(s,y.dots,y.color,v,null)}}function d(){const u=performance.now();o.t+=.04,s.clearRect(0,0,J,J),s.fillStyle="#000",s.fillRect(0,0,J,J);let f=1,h=0;if(o.transitionStart!==null){const v=u-o.transitionStart;if(v>=380)o.transitionStart=null,o.previousId=null;else{const m=v/380,g=m<.5?2*m*m:1-(-2*m+2)**2/2;f=g,h=1-g}}const p=at[o.currentId];!o.blinkStart&&o.transitionStart===null&&(p!=null&&p.canBlink)&&u>=o.nextBlink&&(o.blinkStart=u,o.nextBlink=u+2500+Math.random()*2500),o.blinkStart!==null&&u-o.blinkStart>=340&&(o.blinkStart=null);const b=Gr(o.blinkStart,u);o.previousId&&c(at[o.previousId],h,1,null);const y=o.transitionStart===null?o.t:null;c(p,f,b,y),s.save(),s.globalAlpha=.04,s.fillStyle="#000";for(let v=0;v<J;v+=2)s.fillRect(0,v+1,J,1);s.restore(),o.raf=requestAnimationFrame(d)}return o.raf=requestAnimationFrame(d),()=>cancelAnimationFrame(o.raf)},[]),i.jsx("canvas",{ref:n,width:J,height:J,style:{width:J*t,height:J*t,imageRendering:"pixelated",borderRadius:14,boxShadow:"0 0 40px rgba(0,255,200,0.2)",display:"block"}})}function Le(e,t){const n=[],r=/(\*\*[^*]+?\*\*|__[^_]+?__|`[^`]+?`|\[[^\]]+?\]\([^)]+?\))/g;let a=0,s,o=0;for(;(s=r.exec(e))!==null;){s.index>a&&n.push(e.slice(a,s.index));const c=s[0];if(c.startsWith("**")||c.startsWith("__"))n.push(i.jsx("strong",{children:c.slice(2,-2)},`${t}-b-${o++}`));else if(c.startsWith("`"))n.push(i.jsx("code",{children:c.slice(1,-1)},`${t}-c-${o++}`));else{const d=c.indexOf("]"),u=c.slice(1,d),f=c.slice(d+2,-1);n.push(i.jsx("a",{href:f,target:"_blank",rel:"noreferrer",children:u},`${t}-a-${o++}`))}a=s.index+c.length}return a<e.length&&n.push(e.slice(a)),n}function Xr({text:e}){const n=(e||"").replace(/\r\n/g,`
|
||
`).split(`
|
||
`),r=[];let a=0,s=0;for(;a<n.length;){const o=n[a];if(!o.trim()){a+=1;continue}if(o.startsWith("```")){const u=[];for(a+=1;a<n.length&&!n[a].startsWith("```");)u.push(n[a]),a+=1;a<n.length&&(a+=1),r.push(i.jsx("pre",{className:"bubble-code",children:i.jsx("code",{children:u.join(`
|
||
`)})},`md-${s++}`));continue}const c=o.match(/^(#{1,6})\s+(.*)$/);if(c){const u=Math.min(c[1].length,3),f=`h${u}`;r.push(i.jsx(f,{className:`bubble-heading bubble-heading-${u}`,children:Le(c[2],`h-${s}`)},`md-${s++}`)),a+=1;continue}if(/^\s*[-*+]\s+/.test(o)){const u=[];for(;a<n.length&&/^\s*[-*+]\s+/.test(n[a]);)u.push(n[a].replace(/^\s*[-*+]\s+/,"")),a+=1;r.push(i.jsx("ul",{className:"bubble-list",children:u.map((f,h)=>i.jsx("li",{children:Le(f,`ul-${s}-${h}`)},`md-${s}-${h}`))},`md-${s++}`));continue}if(/^\s*\d+\.\s+/.test(o)){const u=[];for(;a<n.length&&/^\s*\d+\.\s+/.test(n[a]);)u.push(n[a].replace(/^\s*\d+\.\s+/,"")),a+=1;r.push(i.jsx("ol",{className:"bubble-list bubble-list-ordered",children:u.map((f,h)=>i.jsx("li",{children:Le(f,`ol-${s}-${h}`)},`md-${s}-${h}`))},`md-${s++}`));continue}const d=[];for(;a<n.length&&n[a].trim()&&!n[a].startsWith("```")&&!/^(#{1,6})\s+/.test(n[a])&&!/^\s*[-*+]\s+/.test(n[a])&&!/^\s*\d+\.\s+/.test(n[a]);)d.push(n[a]),a+=1;r.push(i.jsx("p",{className:"bubble-paragraph",children:Le(d.join(" "),`p-${s}`)},`md-${s++}`))}return i.jsx("div",{className:"bubble-markdown",children:r})}function Qr({base64:e,mimeType:t="audio/mp3",label:n="🔊"}){const r=e?`data:${t};base64,${e}`:null;return r?i.jsx("audio",{className:"audio-btn",controls:!0,src:r,title:n,preload:"none"}):null}const Zr={terminal:"💻",web_search:"🔍",web_extract:"📄",browser:"🌐",read_file:"📂",write_file:"✏️",execute_code:"⚡",delegate_task:"🤖"};function ea({toolCalls:e}){return!e||e.length===0?null:i.jsxs("details",{className:"tool-calls",children:[i.jsxs("summary",{className:"tool-calls-summary",children:["🔧 Hermes 使用了 ",e.length," 个工具"]}),i.jsx("ul",{className:"tool-calls-list",children:e.map((t,n)=>i.jsxs("li",{className:"tool-calls-item",children:[i.jsx("span",{className:"tool-calls-icon",children:Zr[t.tool]||"🔧"}),i.jsx("span",{className:"tool-calls-name",children:t.tool}),t.preview&&i.jsx("code",{className:"tool-calls-preview",children:t.preview})]},n))})]})}function ta({role:e,text:t,audioBase64:n,audioMime:r,toolCalls:a}){const s=e==="user";return i.jsxs("div",{className:`bubble ${s?"bubble-user":"bubble-bot"}`,children:[i.jsx("div",{className:"bubble-label",children:s?"你":"JBOT"}),!s&&i.jsx(ea,{toolCalls:a}),i.jsx("div",{className:"bubble-text",children:i.jsx(Xr,{text:t})}),n&&i.jsx(Qr,{base64:n,mimeType:r||"audio/mp3"})]})}function na({messages:e,voiceStatus:t}){const n=l.useRef(null),r=Ne();return l.useEffect(()=>{var a;(a=n.current)==null||a.scrollIntoView({behavior:"smooth"})},[e]),i.jsxs("section",{className:"chat-panel",children:[i.jsxs("div",{className:"chat-header",children:[i.jsx("span",{className:"chat-title",children:"对话"}),i.jsx("button",{className:"history-link",onClick:()=>r("/history"),children:"历史记录 →"})]}),t&&i.jsx("div",{className:`voice-status voice-status-${t.type}`,children:t.text}),i.jsxs("div",{className:"chat-messages",children:[e.length===0?i.jsx("p",{className:"chat-empty",children:"按住 Space 开始说话…"}):e.map(a=>i.jsx(ta,{role:a.role,text:a.text,audioBase64:a.audioBase64,audioMime:a.audioMime,toolCalls:a.toolCalls},a.id)),i.jsx("div",{ref:n})]})]})}const Ve="jbot_memory",ra=100;function xe(){try{return JSON.parse(localStorage.getItem(Ve)||"[]")}catch{return[]}}function aa(e){const t=xe(),n=e.toLowerCase().trim();if(t.some(a=>a.text.toLowerCase().trim()===n))return null;const r={id:crypto.randomUUID(),text:e.trim(),createdAt:Date.now()};return localStorage.setItem(Ve,JSON.stringify([r,...t].slice(0,ra))),r}function sa(e){localStorage.setItem(Ve,JSON.stringify(xe().filter(t=>t.id!==e)))}function oa(){localStorage.removeItem(Ve)}function ia({memories:e,onMemoriesChange:t}){const[n,r]=l.useState(!1),a=o=>{sa(o),t()},s=()=>{window.confirm("清空所有记忆?")&&(oa(),t())};return i.jsxs("div",{className:"memory-panel",children:[i.jsxs("button",{className:"memory-toggle",onClick:()=>r(o=>!o),children:[i.jsx("span",{children:"🧠 长期记忆"}),i.jsx("span",{className:"memory-badge",children:e.length}),i.jsx("span",{className:"memory-arrow",children:n?"▲":"▼"})]}),n&&i.jsx("div",{className:"memory-body",children:e.length===0?i.jsx("p",{className:"memory-empty",children:"对话后会自动记住关于你的信息"}):i.jsxs(i.Fragment,{children:[i.jsx("ul",{className:"memory-list",children:e.map(o=>i.jsxs("li",{className:"memory-item",children:[i.jsx("span",{className:"memory-text",children:o.text}),i.jsx("button",{className:"memory-del",onClick:()=>a(o.id),title:"删除",children:"×"})]},o.id))}),i.jsx("button",{className:"memory-clear",onClick:s,children:"清空全部"})]})})]})}const ue="/api/jbot";async function la(){return(await fetch(`${ue}/config/`)).json()}async function ca(e,t=[],n={},r){const a=await fetch(`${ue}/chat/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,memories:t,settings:n}),signal:r});if(!a.ok){const s=await a.json().catch(()=>({}));throw new Error(s.error||`HTTP ${a.status}`)}return a.json()}async function ua(e,t="audio/webm"){const n=await fetch(`${ue}/asr/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({audioBase64:e,format:t})});if(!n.ok){const r=await n.json().catch(()=>({}));throw new Error(r.error||`HTTP ${n.status}`)}return n.json()}async function da(e,t){const n=await fetch(`${ue}/tts/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:e,voice:t})});if(!n.ok){const r=await n.json().catch(()=>({}));throw new Error(r.error||`HTTP ${n.status}`)}return n.json()}async function ha(e,t){try{const n=await fetch(`${ue}/memory/extract/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userText:e,botText:t})});if(!n.ok)return[];const{facts:r=[]}=await n.json();return r}catch{return[]}}async function fa(){try{const e=await fetch(`${ue}/api-config/`);return e.ok?e.json():{}}catch{return{}}}async function ma(e){const t=await fetch(`${ue}/api-config/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok){const n=await t.json().catch(()=>({}));throw new Error(n.error||`HTTP ${t.status}`)}return t.json()}function pa(){const[e,t]=l.useState(!1),n=l.useRef(null),r=l.useRef(null),a=l.useRef(null),s=l.useRef([]),o=l.useRef(""),c=l.useCallback(async()=>{var p;if(e)return;s.current=[],o.current="",(p=n.current)!=null&&p.active||(n.current=await navigator.mediaDevices.getUserMedia({audio:!0}));const u=MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":"audio/webm",f=new MediaRecorder(n.current,{mimeType:u});f.ondataavailable=b=>{b.data.size>0&&s.current.push(b.data)},f.start(100),r.current=f;const h=window.SpeechRecognition||window.webkitSpeechRecognition;if(h){const b=new h;b.lang="zh-CN",b.interimResults=!0,b.continuous=!0,b.onresult=y=>{let v="";for(const m of y.results)m.isFinal&&(v+=m[0].transcript);v&&(o.current=v)},b.onerror=y=>{console.warn("SpeechRecognition error:",y.error)},b.start(),a.current=b}t(!0)},[e]),d=l.useCallback(()=>new Promise(u=>{var p,b;t(!1);const f=o.current;try{(p=a.current)==null||p.stop()}catch{}a.current=null,(b=n.current)==null||b.getTracks().forEach(y=>y.stop()),n.current=null;const h=r.current;if(!h)return u({transcript:f,audioBase64:null,mimeType:null});h.onstop=async()=>{const y=h.mimeType;if(s.current.length===0)return u({transcript:f,audioBase64:null,mimeType:y});const v=new Blob(s.current,{type:y}),m=new FileReader;m.onloadend=()=>{u({transcript:f,audioBase64:m.result.split(",")[1],mimeType:y})},m.readAsDataURL(v)},h.stop(),r.current=null}),[]);return{isRecording:e,start:c,stop:d}}const Ee="jbot_history",ga=60,ya=12;function It(e){return{...e,userAudioBase64:null,userAudioMime:null,botAudioBase64:null,botAudioMime:null}}function an(e){const t=e.slice(0,ga);for(let n=Math.min(ya,t.length);n>=0;n-=1){const r=t.map((a,s)=>s<n?a:It(a));try{return localStorage.setItem(Ee,JSON.stringify(r)),r}catch(a){if((a==null?void 0:a.name)!=="QuotaExceededError"&&(a==null?void 0:a.code)!==22)throw a}}for(let n=Math.min(t.length,20);n>=1;n-=1){const r=t.slice(0,n).map(It);try{return localStorage.setItem(Ee,JSON.stringify(r)),r}catch(a){if((a==null?void 0:a.name)!=="QuotaExceededError"&&(a==null?void 0:a.code)!==22)throw a}}return localStorage.removeItem(Ee),[]}function He(){try{return JSON.parse(localStorage.getItem(Ee)||"[]")}catch{return[]}}function ba(e){const t=He(),n=[{id:crypto.randomUUID(),timestamp:Date.now(),...e},...t];return an(n)[0]||n[0]}function va(){localStorage.removeItem(Ee)}function wa(e){an(He().filter(t=>t.id!==e))}const xa=[{id:"zh_female_vv_uranus_bigtts",label:"灵儿",lang:"中文",gender:"女",style:"亲切"},{id:"zh_female_tianmei_conversation_bigtts",label:"甜美",lang:"中文",gender:"女",style:"温柔"},{id:"zh_female_linjing_conversation_bigtts",label:"琳静",lang:"中文",gender:"女",style:"知性"},{id:"zh_female_qingxin_conversation_bigtts",label:"清新",lang:"中文",gender:"女",style:"清新"},{id:"zh_male_m191_uranus_bigtts",label:"豪远",lang:"中文",gender:"男",style:"标准"},{id:"zh_male_haoran_conversation_bigtts",label:"豪然",lang:"中文",gender:"男",style:"稳重"},{id:"zh_male_m372_conversation_bigtts",label:"温和男声",lang:"中文",gender:"男",style:"温和"},{id:"en_female_sarah_jupiter_bigtts",label:"Sarah",lang:"EN",gender:"女",style:"Warm"},{id:"en_male_adam_mars_bigtts",label:"Adam",lang:"EN",gender:"男",style:"Clear"}],sn="zh_female_vv_uranus_bigtts",pt="jbot_settings",st={robotName:"JBOT",robotPersonality:"你是一个友好、简洁、偶尔幽默的AI机器人助手。回复控制在80字以内。",language:"auto",voiceId:sn,customVoiceId:"",responseMaxWords:80,switchIntervalMs:1e4};function ke(){try{const e=JSON.parse(localStorage.getItem(pt)||"{}");return{...st,...e}}catch{return{...st}}}function Ea(e){const n={...ke(),...e};return localStorage.setItem(pt,JSON.stringify(n)),n}function Ra(){return localStorage.removeItem(pt),{...st}}function ka(e=null){var n;const t=e||ke();return((n=t.customVoiceId)==null?void 0:n.trim())||t.voiceId||sn}const Sa=mt.filter(e=>e.category==="interaction"),ja=mt.filter(e=>e.category==="auto"),Na={1:"idle",2:"listening",3:"thinking",4:"speaking",5:"happy",6:"error",7:"confused",8:"dreaming",q:"natural_smile",w:"calm_relax",e:"curious_observe",r:"light_joy",t:"side_think",y:"warm_friendly",u:"quiet_listen",i:"focus_gaze"};async function Ca(e,t="audio/mp3"){return new Promise(n=>{const r=new Audio(`data:${t};base64,${e}`);r.onended=n,r.onerror=n,r.play().catch(n)})}function Ta(e){return new Promise(t=>{if(!window.speechSynthesis)return t();const n=new SpeechSynthesisUtterance(e);n.lang="zh-CN",n.rate=1.05,n.onend=t,n.onerror=t,window.speechSynthesis.speak(n)})}function Ma(e){return e?e.replace(/```(?:[a-zA-Z0-9_-]+)?\n([\s\S]*?)```/g,(t,n)=>n).replace(/`([^`]+)`/g,"$1").replace(/!\[([^\]]*)\]\([^)]+\)/g,"$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1").replace(/^\s{0,3}#{1,6}\s+/gm,"").replace(/^\s{0,3}>\s?/gm,"").replace(/^\s*[-*+]\s+/gm,"• ").replace(/^\s*\d+\.\s+/gm,"").replace(/(\*\*|__)(.*?)\1/g,"$2").replace(/(\*|_)(.*?)\1/g,"$2").replace(/\|/g," ").replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
||
`).replace(/\n{3,}/g,`
|
||
|
||
`).trim():""}function Aa({phase:e,onStart:t,onEnd:n,onCancel:r}){const a=e==="thinking"||e==="speaking",s=e!=="idle";let o="🎙 按住说话",c="";e==="acquiring"?(o="⏳ 准备中…",c=" vbtn--acquiring"):e==="listening"?(o="🔴 松开发送",c=" vbtn--recording"):e==="thinking"?(o="⚙ 思考中…",c=" vbtn--busy"):e==="speaking"&&(o="🔊 播放中…",c=" vbtn--busy");const d=f=>{f.preventDefault(),a||t()},u=f=>{f.preventDefault(),n()};return i.jsxs("div",{className:"vbtn-wrap",children:[i.jsx("button",{className:`vbtn${c}`,disabled:a,onMouseDown:d,onMouseUp:u,onMouseLeave:u,onTouchStart:d,onTouchEnd:u,onTouchCancel:u,children:o}),s&&i.jsx("button",{className:"vbtn-cancel",onClick:r,title:"取消",children:"✕"})]})}function $a(){var yt;const e=Ne(),[t,n]=l.useState(be[0]),[r,a]=l.useState(!0),[s,o]=l.useState(1),[c]=l.useState(()=>ke().switchIntervalMs??1e4),d=l.useRef(null),u=l.useRef(!0),f=l.useRef(be[0]),h=l.useRef(null),p=l.useRef(c);l.useEffect(()=>{u.current=r},[r]),l.useEffect(()=>{f.current=t},[t]);const b=l.useCallback(()=>{clearTimeout(d.current),d.current=null},[]);h.current=()=>{if(b(),!u.current)return;const E=1+(Math.random()-.5)*.3;d.current=setTimeout(()=>{var P;const O=be.filter(ae=>ae!==f.current),_=O[Math.floor(Math.random()*O.length)];n(_),(P=h.current)==null||P.call(h)},p.current*E)};const y=l.useCallback(()=>{var E;return(E=h.current)==null?void 0:E.call(h)},[]);l.useEffect(()=>(r?y():b(),b),[r,y,b]);const v=l.useCallback(E=>{b(),n(E),u.current&&y()},[b,y]),{start:m,stop:g}=pa(),[x,w]=l.useState("idle"),[$,R]=l.useState(null),[U,V]=l.useState([]),[X,ie]=l.useState([]),[me,Ke]=l.useState(()=>xe()),[le,Te]=l.useState(!1),Q=l.useRef("idle"),I=l.useRef(!1),Je=l.useCallback(()=>Ke(xe()),[]),Me=l.useRef(null),on=l.useCallback(()=>{var O;I.current=!1;const E=Q.current;(E==="listening"||E==="acquiring")&&g().catch(()=>{}),(O=Me.current)==null||O.abort(),Me.current=null,w("idle"),R(null),n("idle"),y()},[y,g]);l.useEffect(()=>{la().then(E=>{(E==null?void 0:E.backendMode)==="hermes"&&Te(!0)}).catch(()=>{})},[]),l.useEffect(()=>{Q.current=x},[x]);const gt=(E,O,_,P,ae)=>{const K={id:crypto.randomUUID(),role:E,text:O,audioBase64:_,audioMime:P,toolCalls:ae};return V(Ae=>[...Ae.slice(-29),K]),K},qe=l.useCallback(async()=>{if(!(I.current||Q.current!=="idle")){I.current=!0,b(),w("acquiring"),R({type:"acquiring",text:"⏳ 麦克风准备中…"});try{await m()}catch(E){console.warn("[PTT] Mic acquisition failed:",E.message),I.current=!1,w("idle"),R({type:"error",text:"⚠ 麦克风不可用"}),setTimeout(()=>R(null),2500),y();return}if(!I.current){g().catch(()=>{}),w("idle"),R(null),y();return}n("listening"),w("listening"),R({type:"listening",text:"🎙 请讲话 · 松开结束"})}},[b,m,g,y]),ce=l.useCallback(async()=>{var wt;if(!I.current)return;if(I.current=!1,Q.current==="acquiring"){w("idle"),R(null),y();return}if(Q.current!=="listening")return;w("thinking"),n("thinking"),R({type:"thinking",text:"⚙ 识别中…"});const{transcript:E,audioBase64:O,mimeType:_}=await g();let P="";if(O)try{R({type:"thinking",text:"⚙ 识别中…"});const{text:A}=await ua(O,_||"audio/webm");P=(A==null?void 0:A.trim())||""}catch(A){console.warn("[ASR] Volcengine failed, using browser transcript:",A.message)}if(P||(P=E.trim()),!P){w("idle"),n("idle"),R(null);return}gt("user",P,O,_),R({type:"thinking",text:"⚙ 思考中…"});const ae=new AbortController;Me.current=ae;let K="",Ae=[];try{const A=le?[]:xe().map(un=>un.text),ge=ke(),$e=[...X,{role:"user",content:P}],xt=await ca($e.slice(-10),A,ge,ae.signal);K=xt.text,Ae=xt.toolCalls||[],ie([...$e,{role:"assistant",content:K}].slice(-20))}catch(A){if(A.name==="AbortError"){w("idle"),n("idle"),R(null),y();return}K=A.message.includes("Cannot connect to Hermes")?`⚠ Hermes Agent 无法连接,请检查 ${((wt=A.message.match(/at (.+?) —/))==null?void 0:wt[1])??"地址"} 是否在线`:`对话出错: ${A.message}`}if(ae.signal.aborted){w("idle"),n("idle"),R(null),y();return}n("thinking"),w("speaking"),R({type:"tts",text:"🔊 生成语音中…"});const ln=ka(),bt=Ma(K);let pe=null,vt=!1;try{const{audioBase64:A}=await da(bt,ln);pe=A}catch(A){console.warn("[TTS] Volcengine unavailable, using browser TTS:",A.message),vt=!0}R({type:"speaking",text:vt?"🔊 播放中… (浏览器语音)":"🔊 播放中…"}),gt("bot",K,pe,"audio/mp3",Ae),ba({userText:P,botText:K,userAudioBase64:O,userAudioMime:_,botAudioBase64:pe,botAudioMime:"audio/mp3"}),le||ha(P,K).then(A=>{let ge=!1;A.forEach($e=>{aa($e)&&(ge=!0)}),ge&&Je()}).catch(()=>{}),ae.signal.aborted||(n("speaking"),pe?(R({type:"speaking",text:"🔊 播放中…"}),await Ca(pe,"audio/mp3")):(R({type:"speaking",text:"🔊 播放中… (浏览器语音)"}),await Ta(bt))),Me.current=null,w("idle"),R(null);const cn=be[Math.floor(Math.random()*be.length)];n(cn),y()},[g,X,y,le,Je]);l.useEffect(()=>{function E(_){if(!(_.target.tagName==="INPUT"||_.target.tagName==="TEXTAREA")){if(_.code==="Space"&&!_.repeat){_.preventDefault(),qe();return}if(Q.current==="idle"){const P=Na[_.key.toLowerCase()];P&&v(P)}}}function O(_){_.code==="Space"&&(_.preventDefault(),ce())}return window.addEventListener("keydown",E),window.addEventListener("keyup",O),()=>{window.removeEventListener("keydown",E),window.removeEventListener("keyup",O)}},[qe,ce,v]),l.useEffect(()=>{const E=()=>ce();return window.addEventListener("mouseup",E),window.addEventListener("touchend",E,{passive:!0}),window.addEventListener("touchcancel",E,{passive:!0}),()=>{window.removeEventListener("mouseup",E),window.removeEventListener("touchend",E),window.removeEventListener("touchcancel",E)}},[ce]);const Ge=l.useRef(null);return l.useEffect(()=>(x==="listening"?Ge.current=setTimeout(()=>{console.warn("[PTT] Auto-stop: max recording time reached"),ce()},6e4):clearTimeout(Ge.current),()=>clearTimeout(Ge.current)),[x,ce]),i.jsxs("div",{className:"app",children:[i.jsxs("header",{className:"hdr",children:[i.jsx("a",{href:"/",className:"hdr-home",title:"返回主页",children:"🏠"}),i.jsxs("h1",{children:["J",i.jsx("span",{className:"accent",children:"BOT"})]}),i.jsx("p",{className:"subtitle",children:"AI Robot Face · 240×240"}),i.jsxs("nav",{className:"hdr-nav",children:[i.jsx("button",{className:"hdr-link",onClick:()=>e("/history"),children:"历史"}),i.jsx("button",{className:"hdr-link",onClick:()=>e("/settings"),children:"设置"})]})]}),i.jsxs("div",{className:"page-body",children:[i.jsxs("aside",{className:"left-col",children:[i.jsxs("section",{className:"screen-wrap",children:[i.jsxs("div",{className:"scale-controls",children:[i.jsx("button",{className:`scale-btn${s===1?" active":""}`,onClick:()=>o(1),children:"1×"}),i.jsx("button",{className:`scale-btn${s===2?" active":""}`,onClick:()=>o(2),children:"2×"})]}),i.jsx("div",{className:"bezel",children:i.jsx(Yr,{expressionId:t,scale:s})}),i.jsx("div",{className:"expr-label",children:(yt=at[t])==null?void 0:yt.label})]}),i.jsxs("section",{className:"panel",children:[i.jsxs("div",{className:"panel-section",children:[i.jsxs("h3",{children:["交互状态 ",i.jsx("span",{className:"key-hint",children:"1 – 8"})]}),i.jsx("div",{className:"btn-grid",children:Sa.map(E=>i.jsx("button",{className:`ebtn${t===E.id?" active":""}`,style:{"--c":E.color},onClick:()=>v(E.id),children:E.label},E.id))})]}),i.jsxs("div",{className:"panel-section",children:[i.jsxs("h3",{children:["微表情 ",i.jsx("span",{className:"key-hint",children:"Q–I · 自动"})]}),i.jsx("div",{className:"btn-grid btn-grid-4",children:ja.map(E=>i.jsx("button",{className:`ebtn${t===E.id?" active":""}`,style:{"--c":E.color},onClick:()=>v(E.id),children:E.label},E.id))})]}),i.jsxs("label",{className:"toggle",children:[i.jsx("input",{type:"checkbox",checked:r,onChange:E=>a(E.target.checked)}),i.jsx("span",{children:"自动轮换微表情"})]})]})]}),i.jsxs("div",{className:"right-col",children:[!le&&i.jsx(ia,{memories:me,onMemoriesChange:Je}),le&&i.jsx("div",{className:"hermes-mode-badge",children:"🧠 Hermes Agent 模式 · 记忆由 Agent 管理"}),i.jsx(na,{messages:U,voiceStatus:$}),i.jsx(Aa,{phase:x,onStart:qe,onEnd:ce,onCancel:on})]})]})]})}function Pt({base64:e,mimeType:t="audio/mp3"}){return e?i.jsx("audio",{className:"hist-audio",controls:!0,src:`data:${t};base64,${e}`,preload:"none"}):null}function _a({entry:e,onDelete:t}){const r=new Date(e.timestamp).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"});return i.jsxs("article",{className:"hist-entry",children:[i.jsxs("div",{className:"hist-meta",children:[i.jsx("span",{className:"hist-time",children:r}),i.jsx("button",{className:"hist-del",onClick:()=>t(e.id),title:"删除",children:"✕"})]}),i.jsxs("div",{className:"hist-row hist-row-user",children:[i.jsx("div",{className:"hist-role",children:"你"}),i.jsxs("div",{className:"hist-body",children:[i.jsx("p",{className:"hist-text",children:e.userText||"(语音消息)"}),i.jsx(Pt,{base64:e.userAudioBase64,mimeType:e.userAudioMime||"audio/webm"})]})]}),i.jsxs("div",{className:"hist-row hist-row-bot",children:[i.jsx("div",{className:"hist-role",children:"JBOT"}),i.jsxs("div",{className:"hist-body",children:[i.jsx("p",{className:"hist-text",children:e.botText||""}),i.jsx(Pt,{base64:e.botAudioBase64,mimeType:"audio/mp3"})]})]})]})}function Ia(){const[e,t]=l.useState(()=>He()),n=Ne(),r=s=>{wa(s),t(He())},a=()=>{window.confirm("确认清空所有历史记录?")&&(va(),t([]))};return i.jsxs("div",{className:"hist-page",children:[i.jsxs("div",{className:"hist-toolbar",children:[i.jsx("button",{className:"hist-back",onClick:()=>n("/"),children:"← 返回"}),i.jsx("h1",{className:"hist-heading",children:"历史对话"}),i.jsx("button",{className:"hist-clear",onClick:a,disabled:e.length===0,children:"清空"})]}),e.length===0?i.jsx("p",{className:"hist-empty",children:"暂无历史记录"}):i.jsx("div",{className:"hist-list",children:e.map(s=>i.jsx(_a,{entry:s,onDelete:r},s.id))})]})}const Lt={volcAppId:"",volcAccessToken:"",openrouterApiKey:"",llmModel:"deepseek/deepseek-chat",volcTtsVoice:"zh_female_vv_uranus_bigtts",volcAsrResource:"volc.bigasr.sauc.duration",hermesUrl:"http://192.168.1.10:8642",hermesApiKey:"",backendMode:"openrouter"};function Pa(){const e=Ne(),[t,n]=l.useState(()=>ke()),[r,a]=l.useState(Lt),[s,o]=l.useState(!0),[c,d]=l.useState(!1),[u,f]=l.useState({});l.useEffect(()=>{fa().then(m=>{m&&!m.error&&a(g=>({...g,...m}))}).finally(()=>o(!1))},[]);const h=(m,g)=>{n(x=>({...x,[m]:g})),d(!1)},p=(m,g)=>{a(x=>({...x,[m]:g})),d(!1)},b=m=>f(g=>({...g,[m]:!g[m]})),y=async()=>{Ea(t);try{await ma(r),d(!0),setTimeout(()=>d(!1),2e3)}catch(m){alert("API 配置保存失败:"+m.message)}},v=()=>{if(window.confirm("重置所有设置为默认值?")){const m=Ra();n(m),a(Lt),d(!1)}};return i.jsxs("div",{className:"settings-page",children:[i.jsxs("div",{className:"settings-toolbar",children:[i.jsx("button",{className:"settings-back",onClick:()=>e("/"),children:"← 返回"}),i.jsx("h1",{className:"settings-heading",children:"全局设置"}),i.jsx("button",{className:"settings-save",onClick:y,children:c?"✓ 已保存":"保存"})]}),i.jsxs("div",{className:"settings-body",children:[i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🔑 API 配置"}),i.jsx("p",{className:"settings-hint-block",children:"配置保存在服务器数据库中。Token 字段显示 *** 表示已配置,留空则保持不变。"}),s?i.jsx("p",{className:"settings-hint-block",children:"加载中…"}):i.jsxs(i.Fragment,{children:[i.jsxs("label",{className:"settings-label",children:["Volcengine App ID",i.jsx("input",{className:"settings-input",value:r.volcAppId,onChange:m=>p("volcAppId",m.target.value),placeholder:"填写火山引擎 App ID"})]}),i.jsxs("label",{className:"settings-label",children:["Volcengine Access Token",i.jsxs("div",{className:"settings-secret-row",children:[i.jsx("input",{className:"settings-input",type:u.volcAccessToken?"text":"password",value:r.volcAccessToken,onChange:m=>p("volcAccessToken",m.target.value),placeholder:"留空则保持不变"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>b("volcAccessToken"),children:u.volcAccessToken?"隐藏":"显示"})]})]}),i.jsxs("label",{className:"settings-label",children:["OpenRouter API Key",i.jsxs("div",{className:"settings-secret-row",children:[i.jsx("input",{className:"settings-input",type:u.openrouterApiKey?"text":"password",value:r.openrouterApiKey,onChange:m=>p("openrouterApiKey",m.target.value),placeholder:"留空则保持不变"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>b("openrouterApiKey"),children:u.openrouterApiKey?"隐藏":"显示"})]})]}),i.jsxs("label",{className:"settings-label",children:["ASR Resource ID",i.jsx("input",{className:"settings-input",value:r.volcAsrResource,onChange:m=>p("volcAsrResource",m.target.value),placeholder:"volc.bigasr.sauc.duration"})]})]})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🧠 AI 后端模式"}),i.jsx("p",{className:"settings-hint-block",children:"选择对话 AI 后端。Hermes Agent 支持工具调用、长期记忆和推理链。"}),i.jsx("div",{className:"settings-radio-group",children:[{value:"openrouter",label:"OpenRouter(直接调用模型)"},{value:"hermes",label:"Hermes Agent(本地 Agent,支持工具/记忆)"}].map(m=>i.jsxs("label",{className:"settings-radio-label",children:[i.jsx("input",{type:"radio",name:"backendMode",value:m.value,checked:r.backendMode===m.value,onChange:()=>p("backendMode",m.value)}),m.label]},m.value))}),r.backendMode==="openrouter"&&i.jsxs("label",{className:"settings-label settings-label-mt",children:["LLM 模型",i.jsx("input",{className:"settings-input",value:r.llmModel,onChange:m=>p("llmModel",m.target.value),placeholder:"deepseek/deepseek-chat"}),i.jsx("span",{className:"settings-hint",children:"OpenRouter 模型 ID,例如 openai/gpt-4o"})]}),r.backendMode==="hermes"&&i.jsxs(i.Fragment,{children:[i.jsxs("label",{className:"settings-label settings-label-mt",children:["Hermes Agent URL",i.jsx("input",{className:"settings-input",value:r.hermesUrl,onChange:m=>p("hermesUrl",m.target.value),placeholder:"http://192.168.1.10:8642"}),i.jsx("span",{className:"settings-hint",children:"本地 Hermes 实例地址,需开启 API_SERVER_ENABLED=true"})]}),i.jsxs("label",{className:"settings-label",children:["Hermes API Key",i.jsxs("div",{className:"settings-secret-row",children:[i.jsx("input",{className:"settings-input",type:u.hermesApiKey?"text":"password",value:r.hermesApiKey,onChange:m=>p("hermesApiKey",m.target.value),placeholder:"留空则不鉴权(局域网内可不填)"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>b("hermesApiKey"),children:u.hermesApiKey?"隐藏":"显示"})]})]}),i.jsx("p",{className:"settings-hint-block",children:"💡 Hermes 模式下,中间工具调用不会转语音,只有最终回答会朗读。工具调用进度会显示在聊天界面。"})]})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🤖 机器人身份"}),i.jsxs("label",{className:"settings-label",children:["名字",i.jsx("input",{className:"settings-input",value:t.robotName,onChange:m=>h("robotName",m.target.value),placeholder:"JBOT"})]}),i.jsxs("label",{className:"settings-label",children:["人格描述 ",i.jsx("span",{className:"settings-hint",children:"会注入到每轮对话的系统提示"}),i.jsx("textarea",{className:"settings-textarea",rows:3,value:t.robotPersonality,onChange:m=>h("robotPersonality",m.target.value),placeholder:"你是一个友好、简洁、偶尔幽默的AI机器人助手。回复控制在80字以内。"})]}),i.jsxs("div",{className:"settings-label",children:["微表情切换间隔",i.jsxs("div",{className:"settings-slider-row",children:[i.jsx("input",{type:"range",min:"3",max:"30",step:"1",value:Math.round((t.switchIntervalMs??1e4)/1e3),onChange:m=>h("switchIntervalMs",Number(m.target.value)*1e3),className:"settings-slider"}),i.jsxs("span",{className:"settings-slider-val",children:[Math.round((t.switchIntervalMs??1e4)/1e3)," 秒"]})]})]})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"👤 用户背景"}),i.jsxs("label",{className:"settings-label",children:["关于你 ",i.jsx("span",{className:"settings-hint",children:"机器人会了解你的背景,更好地回答"}),i.jsx("textarea",{className:"settings-textarea",rows:3,value:t.extraContext||"",onChange:m=>h("extraContext",m.target.value),placeholder:"例如:我叫小明,是一名软件工程师,在上海工作,对AI和嵌入式系统感兴趣。"})]})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🌐 语言"}),i.jsx("div",{className:"settings-radio-group",children:[{value:"auto",label:"自动(跟随用户语言)"},{value:"zh-CN",label:"中文"},{value:"en-US",label:"English"}].map(m=>i.jsxs("label",{className:"settings-radio-label",children:[i.jsx("input",{type:"radio",name:"language",value:m.value,checked:t.language===m.value,onChange:()=>h("language",m.value)}),m.label]},m.value))})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🔊 语音音色"}),i.jsx("div",{className:"settings-voice-grid",children:xa.map(m=>i.jsxs("button",{className:`settings-voice-btn ${!t.customVoiceId&&t.voiceId===m.id?"active":""}`,onClick:()=>{h("voiceId",m.id),h("customVoiceId","")},children:[i.jsx("span",{className:"voice-btn-label",children:m.label}),i.jsxs("span",{className:"voice-btn-meta",children:[m.lang," · ",m.gender," · ",m.style]})]},m.id))}),i.jsxs("label",{className:"settings-label settings-label-mt",children:["自定义音色 ID ",i.jsx("span",{className:"settings-hint",children:"填写后会覆盖上方选择"}),i.jsx("input",{className:"settings-input",value:t.customVoiceId||"",onChange:m=>h("customVoiceId",m.target.value),placeholder:"例如 zh_female_vv_uranus_bigtts"})]}),i.jsxs("p",{className:"settings-hint-block",children:["完整音色列表见"," ",i.jsx("a",{href:"https://www.volcengine.com/docs/6561/1257544",target:"_blank",rel:"noreferrer",children:"火山引擎 TTS 音色文档"})]})]}),i.jsxs("section",{className:"settings-section settings-section-danger",children:[i.jsx("h2",{className:"settings-section-title",children:"⚠️ 重置"}),i.jsx("button",{className:"settings-reset-btn",onClick:v,children:"重置为默认设置"})]})]})]})}dn.createRoot(document.getElementById("jbot-root")).render(i.jsx(l.StrictMode,{children:i.jsx(_r,{basename:"/jbot",children:i.jsxs(cr,{children:[i.jsx(Be,{path:"/",element:i.jsx($a,{})}),i.jsx(Be,{path:"/history",element:i.jsx(Ia,{})}),i.jsx(Be,{path:"/settings",element:i.jsx(Pa,{})})]})})}));
|