mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
In Hermes mode JBOT is a pure voice UI — memory is owned by the Agent: - Backend: sys prompt excludes local memories when backend_mode=hermes - Backend: config_view now returns backendMode so the frontend can adapt - Frontend: App.jsx loads backendMode on mount via apiConfig() - Frontend: memories not passed to apiChat() when isHermesMode - Frontend: memory extraction (apiExtractMemory) skipped when isHermesMode - Frontend: MemoryPanel hidden in Hermes mode; replaced by subtle '🧠 Hermes Agent 模式 · 记忆由 Agent 管理' badge Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
13 lines
71 KiB
JavaScript
13 lines
71 KiB
JavaScript
import{r as l,j as i,c as tn}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 yt="popstate";function vt(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function nn(e={}){function t(r,a){var d;let s=(d=a.state)==null?void 0:d.masked,{pathname:o,search:u,hash:c}=s||r.location;return Ye("",{pathname:o,search:u,hash:c},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:we(a)}return an(t,n,null,e)}function T(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 rn(){return Math.random().toString(36).substring(2,10)}function bt(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 Ye(e,t,n=null,r,a){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?ue(t):t,state:n,key:t&&t.key||r||rn(),mask:a}}function we({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 ue(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 an(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:s=!1}=r,o=a.history,u="POP",c=null,d=m();d==null&&(d=0,o.replaceState({...o.state,idx:d},""));function m(){return(o.state||{idx:null}).idx}function h(){u="POP";let f=m(),y=f==null?null:f-d;d=f,c&&c({action:u,location:b.location,delta:y})}function p(f,y){u="PUSH";let w=vt(f)?f:Ye(b.location,f,y);d=m()+1;let x=bt(w,d),A=b.createHref(w.mask||w);try{o.pushState(x,"",A)}catch(R){if(R instanceof DOMException&&R.name==="DataCloneError")throw R;a.location.assign(A)}s&&c&&c({action:u,location:b.location,delta:1})}function g(f,y){u="REPLACE";let w=vt(f)?f:Ye(b.location,f,y);d=m();let x=bt(w,d),A=b.createHref(w.mask||w);o.replaceState(x,"",A),s&&c&&c({action:u,location:b.location,delta:0})}function v(f){return sn(f)}let b={get action(){return u},get location(){return e(a,o)},listen(f){if(c)throw new Error("A history only accepts one active listener");return a.addEventListener(yt,h),c=f,()=>{a.removeEventListener(yt,h),c=null}},createHref(f){return t(a,f)},createURL:v,encodeLocation(f){let y=v(f);return{pathname:y.pathname,search:y.search,hash:y.hash}},push:p,replace:g,go(f){return o.go(f)}};return b}function sn(e,t=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),T(n,"No window.location.(origin|href) available to create URL");let r=typeof e=="string"?e:we(e);return r=r.replace(/ $/,"%20"),!t&&r.startsWith("//")&&(r=n+r),new URL(r,n)}function At(e,t,n="/"){return on(e,t,n,!1)}function on(e,t,n,r,a){let s=typeof t=="string"?ue(t):t,o=ee(s.pathname||"/",n);if(o==null)return null;let u=ln(e),c=null,d=wn(o);for(let m=0;c==null&&m<u.length;++m)c=vn(u[m],d,r);return c}function ln(e){let t=Pt(e);return cn(t),t}function Pt(e,t=[],n=[],r="",a=!1){let s=(o,u,c=a,d)=>{let m={relativePath:d===void 0?o.path||"":d,caseSensitive:o.caseSensitive===!0,childrenIndex:u,route:o};if(m.relativePath.startsWith("/")){if(!m.relativePath.startsWith(r)&&c)return;T(m.relativePath.startsWith(r),`Absolute route path "${m.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),m.relativePath=m.relativePath.slice(r.length)}let h=V([r,m.relativePath]),p=n.concat(m);o.children&&o.children.length>0&&(T(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${h}".`),Pt(o.children,t,p,h,c)),!(o.path==null&&!o.index)&&t.push({path:h,score:gn(h,o.index),routesMeta:p})};return e.forEach((o,u)=>{var c;if(o.path===""||!((c=o.path)!=null&&c.includes("?")))s(o,u);else for(let d of It(o.path))s(o,u,!0,d)}),t}function It(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=It(r.join("/")),u=[];return u.push(...o.map(c=>c===""?s:[s,c].join("/"))),a&&u.push(...o),u.map(c=>e.startsWith("/")&&c===""?"/":c)}function cn(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:yn(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var un=/^:[\w-]+$/,dn=3,hn=2,fn=1,mn=10,pn=-2,wt=e=>e==="*";function gn(e,t){let n=e.split("/"),r=n.length;return n.some(wt)&&(r+=pn),t&&(r+=hn),n.filter(a=>!wt(a)).reduce((a,s)=>a+(un.test(s)?dn:s===""?fn:mn),r)}function yn(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 vn(e,t,n=!1){let{routesMeta:r}=e,a={},s="/",o=[];for(let u=0;u<r.length;++u){let c=r[u],d=u===r.length-1,m=s==="/"?t:t.slice(s.length)||"/",h=Le({path:c.relativePath,caseSensitive:c.caseSensitive,end:d},m),p=c.route;if(!h&&d&&n&&!r[r.length-1].route.index&&(h=Le({path:c.relativePath,caseSensitive:c.caseSensitive,end:!1},m)),!h)return null;Object.assign(a,h.params),o.push({params:a,pathname:V([s,h.pathname]),pathnameBase:Sn(V([s,h.pathnameBase])),route:p}),h.pathnameBase!=="/"&&(s=V([s,h.pathnameBase]))}return o}function Le(e,t){typeof e=="string"&&(e={path:e,caseSensitive:!1,end:!0});let[n,r]=bn(e.path,e.caseSensitive,e.end),a=t.match(n);if(!a)return null;let s=a[0],o=s.replace(/(.)\/+$/,"$1"),u=a.slice(1);return{params:r.reduce((d,{paramName:m,isOptional:h},p)=>{if(m==="*"){let v=u[p]||"";o=s.slice(0,s.length-v.length).replace(/(.)\/+$/,"$1")}const g=u[p];return h&&!g?d[m]=void 0:d[m]=(g||"").replace(/%2F/g,"/"),d},{}),pathname:s,pathnameBase:o,pattern:e}}function bn(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,u,c,d,m)=>{if(r.push({paramName:u,isOptional:c!=null}),c){let h=m.charAt(d+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 wn(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 ee(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 xn=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function En(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?ue(e):e,s;return n?(n=Lt(n),n.startsWith("/")?s=xt(n.substring(1),"/"):s=xt(n,t)):s=t,{pathname:s,search:kn(r),hash:Nn(a)}}function xt(e,t){let n=$e(t).split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Ke(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 Rn(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function _t(e){let t=Rn(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function nt(e,t,n,r=!1){let a;typeof e=="string"?a=ue(e):(a={...e},T(!a.pathname||!a.pathname.includes("?"),Ke("?","pathname","search",a)),T(!a.pathname||!a.pathname.includes("#"),Ke("#","pathname","hash",a)),T(!a.search||!a.search.includes("#"),Ke("#","search","hash",a)));let s=e===""||a.pathname==="",o=s?"/":a.pathname,u;if(o==null)u=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("/")}u=h>=0?t[h]:"/"}let c=En(a,u),d=o&&o!=="/"&&o.endsWith("/"),m=(s||o===".")&&n.endsWith("/");return!c.pathname.endsWith("/")&&(d||m)&&(c.pathname+="/"),c}var Lt=e=>e.replace(/\/\/+/g,"/"),V=e=>Lt(e.join("/")),$e=e=>e.replace(/\/+$/,""),Sn=e=>$e(e).replace(/^\/*/,"/"),kn=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Nn=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,Cn=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 jn(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function Mn(e){let t=e.map(n=>n.route.path).filter(Boolean);return V(t)||"/"}var $t=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Bt(e,t){let n=e;if(typeof n!="string"||!xn.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,a=!1;if($t)try{let s=new URL(window.location.href),o=n.startsWith("//")?new URL(s.protocol+n):new URL(n),u=ee(o.pathname,t);o.origin===s.origin&&u!=null?n=u+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 Ft=["POST","PUT","PATCH","DELETE"];new Set(Ft);var Tn=["GET",...Ft];new Set(Tn);var de=l.createContext(null);de.displayName="DataRouter";var Fe=l.createContext(null);Fe.displayName="DataRouterState";var Ot=l.createContext(!1);function An(){return l.useContext(Ot)}var Dt=l.createContext({isTransitioning:!1});Dt.displayName="ViewTransition";var Pn=l.createContext(new Map);Pn.displayName="Fetchers";var In=l.createContext(null);In.displayName="Await";var W=l.createContext(null);W.displayName="Navigation";var Ee=l.createContext(null);Ee.displayName="Location";var te=l.createContext({outlet:null,matches:[],isDataRoute:!1});te.displayName="Route";var rt=l.createContext(null);rt.displayName="RouteError";var Ut="REACT_ROUTER_ERROR",_n="REDIRECT",Ln="ROUTE_ERROR_RESPONSE";function $n(e){if(e.startsWith(`${Ut}:${_n}:{`))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 Bn(e){if(e.startsWith(`${Ut}:${Ln}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new Cn(t.status,t.statusText,t.data)}catch{}}function Fn(e,{relative:t}={}){T(Re(),"useHref() may be used only in the context of a <Router> component.");let{basename:n,navigator:r}=l.useContext(W),{hash:a,pathname:s,search:o}=ke(e,{relative:t}),u=s;return n!=="/"&&(u=s==="/"?n:V([n,s])),r.createHref({pathname:u,search:o,hash:a})}function Re(){return l.useContext(Ee)!=null}function ne(){return T(Re(),"useLocation() may be used only in the context of a <Router> component."),l.useContext(Ee).location}var Ht="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function zt(e){l.useContext(W).static||l.useLayoutEffect(e)}function Se(){let{isDataRoute:e}=l.useContext(te);return e?Xn():On()}function On(){T(Re(),"useNavigate() may be used only in the context of a <Router> component.");let e=l.useContext(de),{basename:t,navigator:n}=l.useContext(W),{matches:r}=l.useContext(te),{pathname:a}=ne(),s=JSON.stringify(_t(r)),o=l.useRef(!1);return zt(()=>{o.current=!0}),l.useCallback((c,d={})=>{if(q(o.current,Ht),!o.current)return;if(typeof c=="number"){n.go(c);return}let m=nt(c,JSON.parse(s),a,d.relative==="path");e==null&&t!=="/"&&(m.pathname=m.pathname==="/"?t:V([t,m.pathname])),(d.replace?n.replace:n.push)(m,d.state,d)},[t,n,s,a,e])}l.createContext(null);function ke(e,{relative:t}={}){let{matches:n}=l.useContext(te),{pathname:r}=ne(),a=JSON.stringify(_t(n));return l.useMemo(()=>nt(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Dn(e,t){return Wt(e,t)}function Wt(e,t,n){var f;T(Re(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:r}=l.useContext(W),{matches:a}=l.useContext(te),s=a[a.length-1],o=s?s.params:{},u=s?s.pathname:"/",c=s?s.pathnameBase:"/",d=s&&s.route;{let y=d&&d.path||"";Kt(u,!d||y.endsWith("*")||y.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${u}" (under <Route path="${y}">) 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="${y}"> to <Route path="${y==="/"?"*":`${y}/*`}">.`)}let m=ne(),h;if(t){let y=typeof t=="string"?ue(t):t;T(c==="/"||((f=y.pathname)==null?void 0:f.startsWith(c)),`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 "${c}" but pathname "${y.pathname}" was given in the \`location\` prop.`),h=y}else h=m;let p=h.pathname||"/",g=p;if(c!=="/"){let y=c.replace(/^\//,"").split("/");g="/"+p.replace(/^\//,"").split("/").slice(y.length).join("/")}let v=n&&n.state.matches.length?n.state.matches.map(y=>Object.assign(y,{route:n.manifest[y.route.id]||y.route})):At(e,{pathname:g});q(d||v!=null,`No routes matched location "${h.pathname}${h.search}${h.hash}" `),q(v==null||v[v.length-1].route.element!==void 0||v[v.length-1].route.Component!==void 0||v[v.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 b=Vn(v&&v.map(y=>Object.assign({},y,{params:Object.assign({},o,y.params),pathname:V([c,r.encodeLocation?r.encodeLocation(y.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:y.pathname]),pathnameBase:y.pathnameBase==="/"?c:V([c,r.encodeLocation?r.encodeLocation(y.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:y.pathnameBase])})),a,n);return t&&b?l.createElement(Ee.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",mask:void 0,...h},navigationType:"POP"}},b):b}function Un(){let e=Yn(),t=jn(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 Hn=l.createElement(Un,null),Vt=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=Bn(e.digest);n&&(e=n)}let t=e!==void 0?l.createElement(te.Provider,{value:this.props.routeContext},l.createElement(rt.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?l.createElement(zn,{error:e},t):t}};Vt.contextType=Ot;var Je=new WeakMap;function zn({children:e,error:t}){let{basename:n}=l.useContext(W);if(typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){let r=$n(t.digest);if(r){let a=Je.get(t);if(a)throw a;let s=Bt(r.location,n);if($t&&!Je.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 Je.set(t,o),o}return l.createElement("meta",{httpEquiv:"refresh",content:`0;url=${s.absoluteURL||s.to}`})}}return e}function Wn({routeContext:e,match:t,children:n}){let r=l.useContext(de);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),l.createElement(te.Provider,{value:e},n)}function Vn(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 m=a.findIndex(h=>h.route.id&&(s==null?void 0:s[h.route.id])!==void 0);T(m>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(s).join(",")}`),a=a.slice(0,Math.min(a.length,m+1))}let o=!1,u=-1;if(n&&r){o=r.renderFallback;for(let m=0;m<a.length;m++){let h=a[m];if((h.route.HydrateFallback||h.route.hydrateFallbackElement)&&(u=m),h.route.id){let{loaderData:p,errors:g}=r,v=h.route.loader&&!p.hasOwnProperty(h.route.id)&&(!g||g[h.route.id]===void 0);if(h.route.lazy||v){n.isStatic&&(o=!0),u>=0?a=a.slice(0,u+1):a=[a[0]];break}}}}let c=n==null?void 0:n.onError,d=r&&c?(m,h)=>{var p,g;c(m,{location:r.location,params:((g=(p=r.matches)==null?void 0:p[0])==null?void 0:g.params)??{},pattern:Mn(r.matches),errorInfo:h})}:void 0;return a.reduceRight((m,h,p)=>{let g,v=!1,b=null,f=null;r&&(g=s&&h.route.id?s[h.route.id]:void 0,b=h.route.errorElement||Hn,o&&(u<0&&p===0?(Kt("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),v=!0,f=null):u===p&&(v=!0,f=h.route.hydrateFallbackElement||null)));let y=t.concat(a.slice(0,p+1)),w=()=>{let x;return g?x=b:v?x=f:h.route.Component?x=l.createElement(h.route.Component,null):h.route.element?x=h.route.element:x=m,l.createElement(Wn,{match:h,routeContext:{outlet:m,matches:y,isDataRoute:r!=null},children:x})};return r&&(h.route.ErrorBoundary||h.route.errorElement||p===0)?l.createElement(Vt,{location:r.location,revalidation:r.revalidation,component:b,error:g,children:w(),routeContext:{outlet:null,matches:y,isDataRoute:!0},onError:d}):w()},null)}function at(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Kn(e){let t=l.useContext(de);return T(t,at(e)),t}function Jn(e){let t=l.useContext(Fe);return T(t,at(e)),t}function qn(e){let t=l.useContext(te);return T(t,at(e)),t}function st(e){let t=qn(e),n=t.matches[t.matches.length-1];return T(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Gn(){return st("useRouteId")}function Yn(){var r;let e=l.useContext(rt),t=Jn("useRouteError"),n=st("useRouteError");return e!==void 0?e:(r=t.errors)==null?void 0:r[n]}function Xn(){let{router:e}=Kn("useNavigate"),t=st("useNavigate"),n=l.useRef(!1);return zt(()=>{n.current=!0}),l.useCallback(async(a,s={})=>{q(n.current,Ht),n.current&&(typeof a=="number"?await e.navigate(a):await e.navigate(a,{fromRouteId:t,...s}))},[e,t])}var Et={};function Kt(e,t,n){!t&&!Et[e]&&(Et[e]=!0,q(!1,n))}l.memo(Qn);function Qn({routes:e,manifest:t,future:n,state:r,isStatic:a,onError:s}){return Wt(e,void 0,{manifest:t,state:r,isStatic:a,onError:s})}function Pe(e){T(!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 Zn({basename:e="/",children:t=null,location:n,navigationType:r="POP",navigator:a,static:s=!1,useTransitions:o}){T(!Re(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let u=e.replace(/^\/*/,"/"),c=l.useMemo(()=>({basename:u,navigator:a,static:s,useTransitions:o,future:{}}),[u,a,s,o]);typeof n=="string"&&(n=ue(n));let{pathname:d="/",search:m="",hash:h="",state:p=null,key:g="default",mask:v}=n,b=l.useMemo(()=>{let f=ee(d,u);return f==null?null:{location:{pathname:f,search:m,hash:h,state:p,key:g,mask:v},navigationType:r}},[u,d,m,h,p,g,r,v]);return q(b!=null,`<Router basename="${u}"> is not able to match the URL "${d}${m}${h}" because it does not start with the basename, so the <Router> won't render anything.`),b==null?null:l.createElement(W.Provider,{value:c},l.createElement(Ee.Provider,{children:t,value:b}))}function er({children:e,location:t}){return Dn(Xe(e),t)}function Xe(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,Xe(r.props.children,s));return}T(r.type===Pe,`[${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>`),T(!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=Xe(r.props.children,s)),n.push(o)}),n}var Ie="get",_e="application/x-www-form-urlencoded";function Oe(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function tr(e){return Oe(e)&&e.tagName.toLowerCase()==="button"}function nr(e){return Oe(e)&&e.tagName.toLowerCase()==="form"}function rr(e){return Oe(e)&&e.tagName.toLowerCase()==="input"}function ar(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function sr(e,t){return e.button===0&&(!t||t==="_self")&&!ar(e)}var Me=null;function or(){if(Me===null)try{new FormData(document.createElement("form"),0),Me=!1}catch{Me=!0}return Me}var ir=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function qe(e){return e!=null&&!ir.has(e)?(q(!1,`"${e}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${_e}"`),null):e}function lr(e,t){let n,r,a,s,o;if(nr(e)){let u=e.getAttribute("action");r=u?ee(u,t):null,n=e.getAttribute("method")||Ie,a=qe(e.getAttribute("enctype"))||_e,s=new FormData(e)}else if(tr(e)||rr(e)&&(e.type==="submit"||e.type==="image")){let u=e.form;if(u==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let c=e.getAttribute("formaction")||u.getAttribute("action");if(r=c?ee(c,t):null,n=e.getAttribute("formmethod")||u.getAttribute("method")||Ie,a=qe(e.getAttribute("formenctype"))||qe(u.getAttribute("enctype"))||_e,s=new FormData(u,e),!or()){let{name:d,type:m,value:h}=e;if(m==="image"){let p=d?`${d}.`:"";s.append(`${p}x`,"0"),s.append(`${p}y`,"0")}else d&&s.append(d,h)}}else{if(Oe(e))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');n=Ie,r=null,a=_e,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 ot(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function Jt(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&&ee(a.pathname,t)==="/"?a.pathname=`${$e(t)}/_root.${r}`:a.pathname=`${$e(a.pathname)}.${r}`,a}async function cr(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 ur(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 dr(e,t,n){let r=await Promise.all(e.map(async a=>{let s=t.routes[a.route.id];if(s){let o=await cr(s,n);return o.links?o.links():[]}return[]}));return pr(r.flat(1).filter(ur).filter(a=>a.rel==="stylesheet"||a.rel==="preload").map(a=>a.rel==="stylesheet"?{...a,rel:"prefetch",as:"style"}:{...a,rel:"prefetch"}))}function Rt(e,t,n,r,a,s){let o=(c,d)=>n[d]?c.route.id!==n[d].route.id:!0,u=(c,d)=>{var m;return n[d].pathname!==c.pathname||((m=n[d].route.path)==null?void 0:m.endsWith("*"))&&n[d].params["*"]!==c.params["*"]};return s==="assets"?t.filter((c,d)=>o(c,d)||u(c,d)):s==="data"?t.filter((c,d)=>{var h;let m=r.routes[c.route.id];if(!m||!m.hasLoader)return!1;if(o(c,d)||u(c,d))return!0;if(c.route.shouldRevalidate){let p=c.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:c.params,defaultShouldRevalidate:!0});if(typeof p=="boolean")return p}return!0}):[]}function hr(e,t,{includeHydrateFallback:n}={}){return fr(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 fr(e){return[...new Set(e)]}function mr(e){let t={},n=Object.keys(e).sort();for(let r of n)t[r]=e[r];return t}function pr(e,t){let n=new Set;return new Set(t),e.reduce((r,a)=>{let s=JSON.stringify(mr(a));return n.has(s)||(n.add(s),r.push({key:s,link:a})),r},[])}function it(){let e=l.useContext(de);return ot(e,"You must render this element inside a <DataRouterContext.Provider> element"),e}function gr(){let e=l.useContext(Fe);return ot(e,"You must render this element inside a <DataRouterStateContext.Provider> element"),e}var lt=l.createContext(void 0);lt.displayName="FrameworkContext";function ct(){let e=l.useContext(lt);return ot(e,"You must render this element inside a <HydratedRouter> element"),e}function yr(e,t){let n=l.useContext(lt),[r,a]=l.useState(!1),[s,o]=l.useState(!1),{onFocus:u,onBlur:c,onMouseEnter:d,onMouseLeave:m,onTouchStart:h}=t,p=l.useRef(null);l.useEffect(()=>{if(e==="render"&&o(!0),e==="viewport"){let b=y=>{y.forEach(w=>{o(w.isIntersecting)})},f=new IntersectionObserver(b,{threshold:.5});return p.current&&f.observe(p.current),()=>{f.disconnect()}}},[e]),l.useEffect(()=>{if(r){let b=setTimeout(()=>{o(!0)},100);return()=>{clearTimeout(b)}}},[r]);let g=()=>{a(!0)},v=()=>{a(!1),o(!1)};return n?e!=="intent"?[s,p,{}]:[s,p,{onFocus:pe(u,g),onBlur:pe(c,v),onMouseEnter:pe(d,g),onMouseLeave:pe(m,v),onTouchStart:pe(h,g)}]:[!1,p,{}]}function pe(e,t){return n=>{e&&e(n),n.defaultPrevented||t(n)}}function vr({page:e,...t}){let n=An(),{router:r}=it(),a=l.useMemo(()=>At(r.routes,e,r.basename),[r.routes,e,r.basename]);return a?n?l.createElement(wr,{page:e,matches:a,...t}):l.createElement(xr,{page:e,matches:a,...t}):null}function br(e){let{manifest:t,routeModules:n}=ct(),[r,a]=l.useState([]);return l.useEffect(()=>{let s=!1;return dr(e,t,n).then(o=>{s||a(o)}),()=>{s=!0}},[e,t,n]),r}function wr({page:e,matches:t,...n}){let r=ne(),{future:a}=ct(),{basename:s}=it(),o=l.useMemo(()=>{if(e===r.pathname+r.search+r.hash)return[];let u=Jt(e,s,a.unstable_trailingSlashAwareDataRequests,"rsc"),c=!1,d=[];for(let m of t)typeof m.route.shouldRevalidate=="function"?c=!0:d.push(m.route.id);return c&&d.length>0&&u.searchParams.set("_routes",d.join(",")),[u.pathname+u.search]},[s,a.unstable_trailingSlashAwareDataRequests,e,r,t]);return l.createElement(l.Fragment,null,o.map(u=>l.createElement("link",{key:u,rel:"prefetch",as:"fetch",href:u,...n})))}function xr({page:e,matches:t,...n}){let r=ne(),{future:a,manifest:s,routeModules:o}=ct(),{basename:u}=it(),{loaderData:c,matches:d}=gr(),m=l.useMemo(()=>Rt(e,t,d,s,r,"data"),[e,t,d,s,r]),h=l.useMemo(()=>Rt(e,t,d,s,r,"assets"),[e,t,d,s,r]),p=l.useMemo(()=>{if(e===r.pathname+r.search+r.hash)return[];let b=new Set,f=!1;if(t.forEach(w=>{var A;let x=s.routes[w.route.id];!x||!x.hasLoader||(!m.some(R=>R.route.id===w.route.id)&&w.route.id in c&&((A=o[w.route.id])!=null&&A.shouldRevalidate)||x.hasClientLoader?f=!0:b.add(w.route.id))}),b.size===0)return[];let y=Jt(e,u,a.unstable_trailingSlashAwareDataRequests,"data");return f&&b.size>0&&y.searchParams.set("_routes",t.filter(w=>b.has(w.route.id)).map(w=>w.route.id).join(",")),[y.pathname+y.search]},[u,a.unstable_trailingSlashAwareDataRequests,c,r,s,m,t,e,o]),g=l.useMemo(()=>hr(h,s),[h,s]),v=br(h);return l.createElement(l.Fragment,null,p.map(b=>l.createElement("link",{key:b,rel:"prefetch",as:"fetch",href:b,...n})),g.map(b=>l.createElement("link",{key:b,rel:"modulepreload",href:b,...n})),v.map(({key:b,link:f})=>l.createElement("link",{key:b,nonce:n.nonce,...f,crossOrigin:f.crossOrigin??n.crossOrigin})))}function Er(...e){return t=>{e.forEach(n=>{typeof n=="function"?n(t):n!=null&&(n.current=t)})}}var Rr=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{Rr&&(window.__reactRouterVersion="7.15.1")}catch{}function Sr({basename:e,children:t,useTransitions:n,window:r}){let a=l.useRef();a.current==null&&(a.current=nn({window:r,v5Compat:!0}));let s=a.current,[o,u]=l.useState({action:s.action,location:s.location}),c=l.useCallback(d=>{n===!1?u(d):l.startTransition(()=>u(d))},[n]);return l.useLayoutEffect(()=>s.listen(c),[s,c]),l.createElement(Zn,{basename:e,children:t,location:o.location,navigationType:o.action,navigator:s,useTransitions:n})}var qt=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Gt=l.forwardRef(function({onClick:t,discover:n="render",prefetch:r="none",relative:a,reloadDocument:s,replace:o,mask:u,state:c,target:d,to:m,preventScrollReset:h,viewTransition:p,defaultShouldRevalidate:g,...v},b){let{basename:f,navigator:y,useTransitions:w}=l.useContext(W),x=typeof m=="string"&&qt.test(m),A=Bt(m,f);m=A.to;let R=Fn(m,{relative:a}),D=ne(),K=null;if(u){let F=nt(u,[],D.mask?D.mask.pathname:"/",!0);f!=="/"&&(F.pathname=F.pathname==="/"?f:V([f,F.pathname])),K=y.createHref(F)}let[X,oe,he]=yr(r,v),He=jr(m,{replace:o,mask:u,state:c,target:d,preventScrollReset:h,relative:a,viewTransition:p,defaultShouldRevalidate:g,useTransitions:w});function le(F){t&&t(F),F.defaultPrevented||He(F)}let Ne=!(A.isExternal||s),re=l.createElement("a",{...v,...he,href:(Ne?K:void 0)||A.absoluteURL||R,onClick:Ne?le:t,ref:Er(b,oe),target:d,"data-discover":!x&&n==="render"?"true":void 0});return X&&!x?l.createElement(l.Fragment,null,re,l.createElement(vr,{page:R})):re});Gt.displayName="Link";var kr=l.forwardRef(function({"aria-current":t="page",caseSensitive:n=!1,className:r="",end:a=!1,style:s,to:o,viewTransition:u,children:c,...d},m){let h=ke(o,{relative:d.relative}),p=ne(),g=l.useContext(Fe),{navigator:v,basename:b}=l.useContext(W),f=g!=null&&Ir(h)&&u===!0,y=v.encodeLocation?v.encodeLocation(h).pathname:h.pathname,w=p.pathname,x=g&&g.navigation&&g.navigation.location?g.navigation.location.pathname:null;n||(w=w.toLowerCase(),x=x?x.toLowerCase():null,y=y.toLowerCase()),x&&b&&(x=ee(x,b)||x);const A=y!=="/"&&y.endsWith("/")?y.length-1:y.length;let R=w===y||!a&&w.startsWith(y)&&w.charAt(A)==="/",D=x!=null&&(x===y||!a&&x.startsWith(y)&&x.charAt(y.length)==="/"),K={isActive:R,isPending:D,isTransitioning:f},X=R?t:void 0,oe;typeof r=="function"?oe=r(K):oe=[r,R?"active":null,D?"pending":null,f?"transitioning":null].filter(Boolean).join(" ");let he=typeof s=="function"?s(K):s;return l.createElement(Gt,{...d,"aria-current":X,className:oe,ref:m,style:he,to:o,viewTransition:u},typeof c=="function"?c(K):c)});kr.displayName="NavLink";var Nr=l.forwardRef(({discover:e="render",fetcherKey:t,navigate:n,reloadDocument:r,replace:a,state:s,method:o=Ie,action:u,onSubmit:c,relative:d,preventScrollReset:m,viewTransition:h,defaultShouldRevalidate:p,...g},v)=>{let{useTransitions:b}=l.useContext(W),f=Ar(),y=Pr(u,{relative:d}),w=o.toLowerCase()==="get"?"get":"post",x=typeof u=="string"&&qt.test(u),A=R=>{if(c&&c(R),R.defaultPrevented)return;R.preventDefault();let D=R.nativeEvent.submitter,K=(D==null?void 0:D.getAttribute("formmethod"))||o,X=()=>f(D||R.currentTarget,{fetcherKey:t,method:K,navigate:n,replace:a,state:s,relative:d,preventScrollReset:m,viewTransition:h,defaultShouldRevalidate:p});b&&n!==!1?l.startTransition(()=>X()):X()};return l.createElement("form",{ref:v,method:w,action:y,onSubmit:r?c:A,...g,"data-discover":!x&&e==="render"?"true":void 0})});Nr.displayName="Form";function Cr(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Yt(e){let t=l.useContext(de);return T(t,Cr(e)),t}function jr(e,{target:t,replace:n,mask:r,state:a,preventScrollReset:s,relative:o,viewTransition:u,defaultShouldRevalidate:c,useTransitions:d}={}){let m=Se(),h=ne(),p=ke(e,{relative:o});return l.useCallback(g=>{if(sr(g,t)){g.preventDefault();let v=n!==void 0?n:we(h)===we(p),b=()=>m(e,{replace:v,mask:r,state:a,preventScrollReset:s,relative:o,viewTransition:u,defaultShouldRevalidate:c});d?l.startTransition(()=>b()):b()}},[h,m,p,n,r,a,t,e,s,o,u,c,d])}var Mr=0,Tr=()=>`__${String(++Mr)}__`;function Ar(){let{router:e}=Yt("useSubmit"),{basename:t}=l.useContext(W),n=Gn(),r=e.fetch,a=e.navigate;return l.useCallback(async(s,o={})=>{let{action:u,method:c,encType:d,formData:m,body:h}=lr(s,t);if(o.navigate===!1){let p=o.fetcherKey||Tr();await r(p,n,o.action||u,{defaultShouldRevalidate:o.defaultShouldRevalidate,preventScrollReset:o.preventScrollReset,formData:m,body:h,formMethod:o.method||c,formEncType:o.encType||d,flushSync:o.flushSync})}else await a(o.action||u,{defaultShouldRevalidate:o.defaultShouldRevalidate,preventScrollReset:o.preventScrollReset,formData:m,body:h,formMethod:o.method||c,formEncType:o.encType||d,replace:o.replace,state:o.state,fromRouteId:n,flushSync:o.flushSync,viewTransition:o.viewTransition})},[r,a,t,n])}function Pr(e,{relative:t}={}){let{basename:n}=l.useContext(W),r=l.useContext(te);T(r,"useFormAction must be used inside a RouteContext");let[a]=r.matches.slice(-1),s={...ke(e||".",{relative:t})},o=ne();if(e==null){s.search=o.search;let u=new URLSearchParams(s.search),c=u.getAll("index");if(c.some(m=>m==="")){u.delete("index"),c.filter(h=>h).forEach(h=>u.append("index",h));let m=u.toString();s.search=m?`?${m}`:""}}return(!e||e===".")&&a.route.index&&(s.search=s.search?s.search.replace(/^\?/,"?index&"):"?index"),n!=="/"&&(s.pathname=s.pathname==="/"?n:V([n,s.pathname])),we(s)}function Ir(e,{relative:t}={}){let n=l.useContext(Dt);T(n!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:r}=Yt("useViewTransitionState"),a=ke(e,{relative:t});if(!n.isTransitioning)return!1;let s=ee(n.currentLocation.pathname,r)||n.currentLocation.pathname,o=ee(n.nextLocation.pathname,r)||n.nextLocation.pathname;return Le(a.pathname,o)!=null||Le(a.pathname,s)!=null}const _=6,ae=2.6,J=240,Q={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 $(e,t,n,r,a,s=5){const o=[],u=new Set;for(let c=r;c<=a;c+=s){const d=c*Math.PI/180,m=Math.round(e+n*Math.cos(d)),h=Math.round(t+n*Math.sin(d)),p=`${m},${h}`;u.has(p)||(u.add(p),o.push([m,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 Qe(e,t,n,r){const a=[],s=new Set,o=Math.round(n);for(let u=-o;u<=o;u++){const c=u/o*Math.PI,d=Math.round(t+r*Math.sin(c)),m=`${e+u},${d}`;s.has(m)||(s.add(m),a.push([e+u,d]))}return a}function _r(e,t,n,r){const a=[],s=Math.round(n);for(let o=-s;o<=s;o++){const u=o+s;a.push([e+o,Math.round(t+(u%4<2?r:-r))])}return a}function St(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 kt(e,t,n,r){const a=[],s=new Set,o=Math.round(r*2*Math.PI*8);for(let u=0;u<=o;u++){const c=u/o*r*2*Math.PI,d=u/o*n,m=Math.round(e+d*Math.cos(c)),h=Math.round(t+d*Math.sin(c)),p=`${m},${h}`;s.has(p)||(s.add(p),a.push([m,h]))}return a}function Ge(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 Nt(e,t){return[...$(e,t-1,1.5,200,360,30),[e,t+1],[e,t+3]]}function Z(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 z(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 ce(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 se(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 Te(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 Ae(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 Lr(e,t){return{wink:$(e,t+1,3,200,340,15)}}function ve(e,t){return $(e,t,5,25,155)}function Ze(e,t){return $(e,t,7,15,165)}function Ct(e,t){return Y(e,t,5)}function $r(e,t){const n=$(e-2,t,4,30,120,10),r=$(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 Br(e,t){const n=$(e-2,t,2,200,340,20),r=$(e+2,t,2,200,340,20),a=Y(e,t+2,3),s=new Set(n.map(([o,u])=>`${o},${u}`));return[...n,...r.filter(([o,u])=>!s.has(`${o},${u}`)),...a]}function Fr(e,t,n){const r=Math.abs(Math.sin(n*1.4));if(r<.25)return $(e,t,4,20,160,8);const a=r<.65?1:2,s=$(e,t-a,3.5,190,350,8),o=$(e,t+a,3,10,170,8),u=new Set(s.map(([c,d])=>`${c},${d}`));return[...s,...o.filter(([c,d])=>!u.has(`${c},${d}`))]}const[S,k]=Q.LE,[N,C]=Q.RE,[j,M]=Q.MO,L="#22CCFF",Or=[{id:"idle",label:"😐 待机",color:"#00FFEE",category:"interaction",canBlink:!0,leftEye:Z(S,k),rightEye:Z(N,C),mouth:ve(j,M)},{id:"listening",label:"👂 聆听",color:"#44AAFF",category:"interaction",canBlink:!0,leftEye:z(S,k),rightEye:z(N,C),mouth:$(j,M,3,0,180)},{id:"thinking",label:"🤔 思考",color:"#FFCC00",category:"interaction",canBlink:!0,leftEye:ce(S,k),rightEye:Z(N,C),mouth:Qe(j,M,5,1),extras:[{dots:Nt(S-1,k-6),color:"#FFCC00",alpha:.75}]},{id:"speaking",label:"💬 说话",color:"#FFFFFF",pupilColor:"#002233",category:"interaction",canBlink:!0,leftEye:Z(S,k),rightEye:Z(N,C),speakingMouth:!0},{id:"happy",label:"😊 开心",color:"#FF44AA",category:"interaction",canBlink:!0,leftEye:{heart:St(S,k)},rightEye:{heart:St(N,C)},mouth:Ze(j,M)},{id:"error",label:"😵 错误",color:"#FF4400",category:"interaction",canBlink:!0,leftEye:{spiral:kt(S,k,4,2)},rightEye:{spiral:kt(N,C,4,2)},mouth:_r(j,M,5,1.5)},{id:"confused",label:"😕 困惑",color:"#BB44FF",category:"interaction",canBlink:!0,leftEye:z(S,k),rightEye:ce(N,C),mouth:Qe(j,M,5,1.5),extras:[{dots:Nt(N+1,C-6),color:"#BB44FF",alpha:.75}]},{id:"dreaming",label:"💤 做梦",color:"#5566FF",category:"interaction",canBlink:!0,leftEye:se(S,k),rightEye:se(N,C),mouth:ve(j,M),extras:[{dots:Ge(24,10),color:"#5566FF",alpha:.85,zzzIndex:0},{dots:Ge(28,7),color:"#7788FF",alpha:.75,zzzIndex:1},{dots:Ge(32,4),color:"#99AAFF",alpha:.65,zzzIndex:2}]}],Xt=[{id:"natural_smile",label:"01 自然微笑",color:L,category:"auto",canBlink:!0,leftEye:Z(S,k),rightEye:Z(N,C),mouth:ve(j,M)},{id:"calm_relax",label:"02 平静放松",color:L,category:"auto",canBlink:!0,leftEye:se(S,k),rightEye:se(N,C),mouth:Ct(j,M)},{id:"curious_observe",label:"03 好奇观察",color:L,category:"auto",canBlink:!0,leftEye:z(S,k),rightEye:z(N,C),mouth:$(j,M,4,30,150,8)},{id:"light_joy",label:"04 轻松愉悦",color:L,category:"auto",canBlink:!0,leftEye:ce(S,k),rightEye:ce(N,C),mouth:Ze(j,M)},{id:"side_think",label:"05 侧目思考",color:L,category:"auto",canBlink:!0,leftEye:Ae(S,k,2),rightEye:Ae(N,C,2),mouth:Qe(j,M,4,1)},{id:"warm_friendly",label:"06 温和友善",color:L,category:"auto",canBlink:!0,leftEye:Te(S,k),rightEye:Te(N,C),mouth:ve(j,M)},{id:"quiet_listen",label:"07 静静聆听",color:L,category:"auto",canBlink:!0,leftEye:Z(S,k),rightEye:Z(N,C),mouth:Y(j,M,4)},{id:"focus_gaze",label:"08 专注注视",color:L,category:"auto",canBlink:!0,leftEye:z(S,k),rightEye:z(N,C),mouth:Ct(j,M)},{id:"quiet_wait",label:"09 安静等待",color:L,category:"auto",canBlink:!0,leftEye:se(S,k),rightEye:se(N,C),mouth:$(j,M,4,30,150,8)},{id:"slow_blink",label:"10 慢眨眼",color:L,category:"auto",canBlink:!0,leftEye:ce(S,k),rightEye:ce(N,C),mouth:ve(j,M)},{id:"look_around",label:"11 左右扫视",color:L,category:"auto",canBlink:!0,leftEye:Ae(S,k,-2),rightEye:Ae(N,C,-2),mouth:Y(j,M,4)},{id:"playful",label:"12 小小调皮",color:L,category:"auto",canBlink:!1,leftEye:Lr(S,k),rightEye:z(N,C),mouth:$r(j,M)},{id:"joyful_wait",label:"13 愉悦期待",color:L,category:"auto",canBlink:!0,leftEye:z(S,k),rightEye:z(N,C),mouth:Ze(j,M)},{id:"slight_surprise",label:"14 轻微惊喜",color:L,category:"auto",canBlink:!0,leftEye:z(S,k),rightEye:z(N,C),mouth:$(j,M,3,0,180,10)},{id:"gentle_gaze",label:"15 温柔注视",color:L,category:"auto",canBlink:!0,leftEye:Te(S,k),rightEye:Te(N,C),mouth:$(j,M,4,30,150,8)},{id:"spaceout",label:"16 发呆放空",color:L,category:"auto",canBlink:!0,leftEye:se(S,k),rightEye:se(N,C),mouth:Br(j,M)}],ut=[...Or,...Xt],ge=Xt.map(e=>e.id),et=Object.fromEntries(ut.map(e=>[e.id,e]));function O(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 u=s*_+_/2,c=o*_+_/2;e.moveTo(u+ae,c),e.arc(u,c,ae,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 u=s*_+_/2,c=o*_+_/2;e.moveTo(u+ae*.38,c),e.arc(u,c,ae*.38,0,Math.PI*2)}e.fill()}else{const s=[],o=[];for(const[c,d]of t){const m=(c*7.3+d*13.1)*.31;(Math.sin(a*1.1+m)>0?s:o).push([c,d])}const u=(c,d,m)=>{if(c.length){e.globalAlpha=Math.max(0,Math.min(1,d)),e.shadowBlur=m,e.shadowColor=n,e.fillStyle=n,e.beginPath();for(const[h,p]of c){const g=h*_+_/2,v=p*_+_/2;e.moveTo(g+ae,v),e.arc(g,v,ae,0,Math.PI*2)}e.fill()}};u(o,r*.68,7),u(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[c,d]of t){const m=c*_+_/2,h=d*_+_/2;e.moveTo(m+ae*.38,h),e.arc(m,h,ae*.38,0,Math.PI*2)}e.fill()}e.restore()}}function ye(e,t,n){return n>=1?e:e.map(([r,a])=>[r,t+(a-t)*n])}function Dr(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 jt(e,t,n,r,a,s,o,u,c){if(!t)return;const d=s||"#001020";t.iris?(O(e,ye(t.iris,r,u),a,o,c),O(e,ye(t.pupil,r,u),d,o,null),t.hl&&O(e,ye(t.hl,r,u),"#ffffff",o*.9,null),t.lash&&O(e,ye(t.lash,r,u),a,o,null)):t.closed!==void 0?(O(e,t.closed,a,o,c),t.lash&&O(e,t.lash,a,o,null)):t.wink?O(e,t.wink,a,o,c):t.heart?O(e,t.heart,a,o,c):t.spiral?O(e,t.spiral,a,o,c):t.star?O(e,t.star,a,o,c):t.pts&&O(e,ye(t.pts,r,u),a,o,c)}function Ur({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 u(d,m,h,p){if(!d)return;jt(s,d.leftEye,Q.LE[0],Q.LE[1],d.color,d.pupilColor,m,h,p),jt(s,d.rightEye,Q.RE[0],Q.RE[1],d.color,d.pupilColor,m,h,p);const g=d.speakingMouth?Fr(Q.MO[0],Q.MO[1],o.t):d.mouth;if(g&&O(s,g,d.color,m,p),d.extras)for(const v of d.extras){let b=m*v.alpha;if(v.zzzIndex!==void 0){const f=o.t-v.zzzIndex*1.2;b*=.35+.65*(Math.sin(f)*.5+.5)}O(s,v.dots,v.color,b,null)}}function c(){const d=performance.now();o.t+=.04,s.clearRect(0,0,J,J),s.fillStyle="#000",s.fillRect(0,0,J,J);let m=1,h=0;if(o.transitionStart!==null){const b=d-o.transitionStart;if(b>=380)o.transitionStart=null,o.previousId=null;else{const f=b/380,y=f<.5?2*f*f:1-(-2*f+2)**2/2;m=y,h=1-y}}const p=et[o.currentId];!o.blinkStart&&o.transitionStart===null&&(p!=null&&p.canBlink)&&d>=o.nextBlink&&(o.blinkStart=d,o.nextBlink=d+2500+Math.random()*2500),o.blinkStart!==null&&d-o.blinkStart>=340&&(o.blinkStart=null);const g=Dr(o.blinkStart,d);o.previousId&&u(et[o.previousId],h,1,null);const v=o.transitionStart===null?o.t:null;u(p,m,g,v),s.save(),s.globalAlpha=.04,s.fillStyle="#000";for(let b=0;b<J;b+=2)s.fillRect(0,b+1,J,1);s.restore(),o.raf=requestAnimationFrame(c)}return o.raf=requestAnimationFrame(c),()=>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 Hr({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 Wr({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 Vr({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(Wr,{toolCalls:a}),i.jsx("div",{className:"bubble-text",children:t}),n&&i.jsx(Hr,{base64:n,mimeType:r||"audio/mp3"})]})}function Kr({messages:e,voiceStatus:t}){const n=l.useRef(null),r=Se();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(Vr,{role:a.role,text:a.text,audioBase64:a.audioBase64,audioMime:a.audioMime,toolCalls:a.toolCalls},a.id)),i.jsx("div",{ref:n})]})]})}const De="jbot_memory",Jr=100;function be(){try{return JSON.parse(localStorage.getItem(De)||"[]")}catch{return[]}}function qr(e){const t=be(),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(De,JSON.stringify([r,...t].slice(0,Jr))),r}function Gr(e){localStorage.setItem(De,JSON.stringify(be().filter(t=>t.id!==e)))}function Yr(){localStorage.removeItem(De)}function Xr({memories:e,onMemoriesChange:t}){const[n,r]=l.useState(!1),a=o=>{Gr(o),t()},s=()=>{window.confirm("清空所有记忆?")&&(Yr(),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 ie="/api/jbot";async function Qr(){return(await fetch(`${ie}/config/`)).json()}async function Zr(e,t=[],n={}){const r=await fetch(`${ie}/chat/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,memories:t,settings:n})});if(!r.ok){const a=await r.json().catch(()=>({}));throw new Error(a.error||`HTTP ${r.status}`)}return r.json()}async function ea(e,t="audio/webm"){const n=await fetch(`${ie}/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 ta(e,t){const n=await fetch(`${ie}/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 na(e,t){try{const n=await fetch(`${ie}/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 ra(){try{const e=await fetch(`${ie}/api-config/`);return e.ok?e.json():{}}catch{return{}}}async function aa(e){const t=await fetch(`${ie}/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 sa(){const[e,t]=l.useState(!1),n=l.useRef(null),r=l.useRef(null),a=l.useRef(null),s=l.useRef([]),o=l.useRef(""),u=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 d=MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":"audio/webm",m=new MediaRecorder(n.current,{mimeType:d});m.ondataavailable=g=>{g.data.size>0&&s.current.push(g.data)},m.start(100),r.current=m;const h=window.SpeechRecognition||window.webkitSpeechRecognition;if(h){const g=new h;g.lang="zh-CN",g.interimResults=!0,g.continuous=!0,g.onresult=v=>{let b="";for(const f of v.results)f.isFinal&&(b+=f[0].transcript);b&&(o.current=b)},g.onerror=v=>{console.warn("SpeechRecognition error:",v.error)},g.start(),a.current=g}t(!0)},[e]),c=l.useCallback(()=>new Promise(d=>{var p,g;t(!1);const m=o.current;try{(p=a.current)==null||p.stop()}catch{}a.current=null,(g=n.current)==null||g.getTracks().forEach(v=>v.stop()),n.current=null;const h=r.current;if(!h)return d({transcript:m,audioBase64:null,mimeType:null});h.onstop=async()=>{const v=h.mimeType;if(s.current.length===0)return d({transcript:m,audioBase64:null,mimeType:v});const b=new Blob(s.current,{type:v}),f=new FileReader;f.onloadend=()=>{d({transcript:m,audioBase64:f.result.split(",")[1],mimeType:v})},f.readAsDataURL(b)},h.stop(),r.current=null}),[]);return{isRecording:e,start:u,stop:c}}const Ue="jbot_history",oa=200;function Be(){try{return JSON.parse(localStorage.getItem(Ue)||"[]")}catch{return[]}}function ia(e){const t=Be(),n=[{id:crypto.randomUUID(),timestamp:Date.now(),...e},...t];return localStorage.setItem(Ue,JSON.stringify(n.slice(0,oa))),n[0]}function la(){localStorage.removeItem(Ue)}function ca(e){localStorage.setItem(Ue,JSON.stringify(Be().filter(t=>t.id!==e)))}const ua=[{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"}],Qt="zh_female_vv_uranus_bigtts",dt="jbot_settings",tt={robotName:"JBOT",robotPersonality:"你是一个友好、简洁、偶尔幽默的AI机器人助手。回复控制在80字以内。",language:"auto",voiceId:Qt,customVoiceId:"",responseMaxWords:80,switchIntervalMs:1e4};function xe(){try{const e=JSON.parse(localStorage.getItem(dt)||"{}");return{...tt,...e}}catch{return{...tt}}}function da(e){const n={...xe(),...e};return localStorage.setItem(dt,JSON.stringify(n)),n}function ha(){return localStorage.removeItem(dt),{...tt}}function fa(e=null){var n;const t=e||xe();return((n=t.customVoiceId)==null?void 0:n.trim())||t.voiceId||Qt}const ma=ut.filter(e=>e.category==="interaction"),pa=ut.filter(e=>e.category==="auto"),ga={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 ya(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 va(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 ba({phase:e,onStart:t,onEnd:n}){const r=e==="thinking"||e==="speaking";let a="🎙 按住说话",s="";e==="acquiring"?(a="⏳ 准备中…",s=" vbtn--acquiring"):e==="listening"?(a="🔴 松开发送",s=" vbtn--recording"):e==="thinking"?(a="⚙ 思考中…",s=" vbtn--busy"):e==="speaking"&&(a="🔊 播放中…",s=" vbtn--busy");const o=c=>{c.preventDefault(),r||t()},u=c=>{c.preventDefault(),n()};return i.jsx("div",{className:"vbtn-wrap",children:i.jsx("button",{className:`vbtn${s}`,disabled:r,onMouseDown:o,onMouseUp:u,onMouseLeave:u,onTouchStart:o,onTouchEnd:u,onTouchCancel:u,children:a})})}function wa(){var mt;const e=Se(),[t,n]=l.useState(ge[0]),[r,a]=l.useState(!0),[s,o]=l.useState(1),[u]=l.useState(()=>xe().switchIntervalMs??1e4),c=l.useRef(null),d=l.useRef(!0),m=l.useRef(ge[0]),h=l.useRef(null),p=l.useRef(u);l.useEffect(()=>{d.current=r},[r]),l.useEffect(()=>{m.current=t},[t]);const g=l.useCallback(()=>{clearTimeout(c.current),c.current=null},[]);h.current=()=>{if(g(),!d.current)return;const E=1+(Math.random()-.5)*.3;c.current=setTimeout(()=>{var I;const U=ge.filter(H=>H!==m.current),P=U[Math.floor(Math.random()*U.length)];n(P),(I=h.current)==null||I.call(h)},p.current*E)};const v=l.useCallback(()=>{var E;return(E=h.current)==null?void 0:E.call(h)},[]);l.useEffect(()=>(r?v():g(),g),[r,v,g]);const b=l.useCallback(E=>{g(),n(E),d.current&&v()},[g,v]),{start:f,stop:y}=sa(),[w,x]=l.useState("idle"),[A,R]=l.useState(null),[D,K]=l.useState([]),[X,oe]=l.useState([]),[he,He]=l.useState(()=>be()),[le,Ne]=l.useState(!1),re=l.useRef("idle"),F=l.useRef(!1),ht=l.useCallback(()=>He(be()),[]);l.useEffect(()=>{Qr().then(E=>{(E==null?void 0:E.backendMode)==="hermes"&&Ne(!0)}).catch(()=>{})},[]),l.useEffect(()=>{re.current=w},[w]);const ft=(E,U,P,I,H)=>{const fe={id:crypto.randomUUID(),role:E,text:U,audioBase64:P,audioMime:I,toolCalls:H};return K(Ve=>[...Ve.slice(-29),fe]),fe},ze=l.useCallback(async()=>{if(!(F.current||re.current!=="idle")){F.current=!0,g(),x("acquiring"),R({type:"acquiring",text:"⏳ 麦克风准备中…"});try{await f()}catch(E){console.warn("[PTT] Mic acquisition failed:",E.message),F.current=!1,x("idle"),R({type:"error",text:"⚠ 麦克风不可用"}),setTimeout(()=>R(null),2500),v();return}n("listening"),x("listening"),R({type:"listening",text:"🎙 请讲话 · 松开结束"})}},[g,f,v]),We=l.useCallback(async()=>{if(!F.current)return;if(F.current=!1,re.current==="acquiring"){x("idle"),R(null),v();return}if(re.current!=="listening")return;x("thinking"),n("thinking"),R({type:"thinking",text:"⚙ 识别中…"});const{transcript:E,audioBase64:U,mimeType:P}=await y();let I="";if(U)try{R({type:"thinking",text:"⚙ 识别中…"});const{text:B}=await ea(U,P||"audio/webm");I=(B==null?void 0:B.trim())||""}catch(B){console.warn("[ASR] Volcengine failed, using browser transcript:",B.message)}if(I||(I=E.trim()),!I){x("idle"),n("idle"),R(null);return}ft("user",I,U,P),R({type:"thinking",text:"⚙ 思考中…"});let H="",fe=[];try{const B=le?[]:be().map(en=>en.text),Ce=xe(),je=[...X,{role:"user",content:I}],gt=await Zr(je.slice(-10),B,Ce);H=gt.text,fe=gt.toolCalls||[],oe([...je,{role:"assistant",content:H}].slice(-20))}catch(B){H=`对话出错: ${B.message}`}n("speaking"),x("speaking"),R({type:"speaking",text:"🔊 播放中…"});const Ve=fa();let me=null,pt=!1;try{const{audioBase64:B}=await ta(H,Ve);me=B}catch(B){console.warn("[TTS] Volcengine unavailable, using browser TTS:",B.message),pt=!0}pt&&R({type:"speaking",text:"🔊 播放中… (浏览器语音)"}),ft("bot",H,me,"audio/mp3",fe),ia({userText:I,botText:H,userAudioBase64:U,userAudioMime:P,botAudioBase64:me,botAudioMime:"audio/mp3"}),le||na(I,H).then(B=>{let Ce=!1;B.forEach(je=>{qr(je)&&(Ce=!0)}),Ce&&ht()}).catch(()=>{}),me?await ya(me,"audio/mp3"):await va(H),x("idle"),R(null);const Zt=ge[Math.floor(Math.random()*ge.length)];n(Zt),v()},[y,X,v]);return l.useEffect(()=>{function E(P){if(!(P.target.tagName==="INPUT"||P.target.tagName==="TEXTAREA")){if(P.code==="Space"&&!P.repeat){P.preventDefault(),ze();return}if(re.current==="idle"){const I=ga[P.key.toLowerCase()];I&&b(I)}}}function U(P){P.code==="Space"&&(P.preventDefault(),We())}return window.addEventListener("keydown",E),window.addEventListener("keyup",U),()=>{window.removeEventListener("keydown",E),window.removeEventListener("keyup",U)}},[ze,We,b]),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(Ur,{expressionId:t,scale:s})}),i.jsx("div",{className:"expr-label",children:(mt=et[t])==null?void 0:mt.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:ma.map(E=>i.jsx("button",{className:`ebtn${t===E.id?" active":""}`,style:{"--c":E.color},onClick:()=>b(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:pa.map(E=>i.jsx("button",{className:`ebtn${t===E.id?" active":""}`,style:{"--c":E.color},onClick:()=>b(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(Xr,{memories:he,onMemoriesChange:ht}),le&&i.jsx("div",{className:"hermes-mode-badge",children:"🧠 Hermes Agent 模式 · 记忆由 Agent 管理"}),i.jsx(Kr,{messages:D,voiceStatus:A}),i.jsx(ba,{phase:w,onStart:ze,onEnd:We})]})]})]})}function Mt({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 xa({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(Mt,{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(Mt,{base64:e.botAudioBase64,mimeType:"audio/mp3"})]})]})]})}function Ea(){const[e,t]=l.useState(()=>Be()),n=Se(),r=s=>{ca(s),t(Be())},a=()=>{window.confirm("确认清空所有历史记录?")&&(la(),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(xa,{entry:s,onDelete:r},s.id))})]})}const Tt={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 Ra(){const e=Se(),[t,n]=l.useState(()=>xe()),[r,a]=l.useState(Tt),[s,o]=l.useState(!0),[u,c]=l.useState(!1),[d,m]=l.useState({});l.useEffect(()=>{ra().then(f=>{f&&!f.error&&a(y=>({...y,...f}))}).finally(()=>o(!1))},[]);const h=(f,y)=>{n(w=>({...w,[f]:y})),c(!1)},p=(f,y)=>{a(w=>({...w,[f]:y})),c(!1)},g=f=>m(y=>({...y,[f]:!y[f]})),v=async()=>{da(t);try{await aa(r),c(!0),setTimeout(()=>c(!1),2e3)}catch(f){alert("API 配置保存失败:"+f.message)}},b=()=>{if(window.confirm("重置所有设置为默认值?")){const f=ha();n(f),a(Tt),c(!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:v,children:u?"✓ 已保存":"保存"})]}),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:f=>p("volcAppId",f.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:d.volcAccessToken?"text":"password",value:r.volcAccessToken,onChange:f=>p("volcAccessToken",f.target.value),placeholder:"留空则保持不变"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>g("volcAccessToken"),children:d.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:d.openrouterApiKey?"text":"password",value:r.openrouterApiKey,onChange:f=>p("openrouterApiKey",f.target.value),placeholder:"留空则保持不变"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>g("openrouterApiKey"),children:d.openrouterApiKey?"隐藏":"显示"})]})]}),i.jsxs("label",{className:"settings-label",children:["ASR Resource ID",i.jsx("input",{className:"settings-input",value:r.volcAsrResource,onChange:f=>p("volcAsrResource",f.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(f=>i.jsxs("label",{className:"settings-radio-label",children:[i.jsx("input",{type:"radio",name:"backendMode",value:f.value,checked:r.backendMode===f.value,onChange:()=>p("backendMode",f.value)}),f.label]},f.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:f=>p("llmModel",f.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:f=>p("hermesUrl",f.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:d.hermesApiKey?"text":"password",value:r.hermesApiKey,onChange:f=>p("hermesApiKey",f.target.value),placeholder:"留空则不鉴权(局域网内可不填)"}),i.jsx("button",{className:"settings-show-btn",onClick:()=>g("hermesApiKey"),children:d.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:f=>h("robotName",f.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:f=>h("robotPersonality",f.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:f=>h("switchIntervalMs",Number(f.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:f=>h("extraContext",f.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(f=>i.jsxs("label",{className:"settings-radio-label",children:[i.jsx("input",{type:"radio",name:"language",value:f.value,checked:t.language===f.value,onChange:()=>h("language",f.value)}),f.label]},f.value))})]}),i.jsxs("section",{className:"settings-section",children:[i.jsx("h2",{className:"settings-section-title",children:"🔊 语音音色"}),i.jsx("div",{className:"settings-voice-grid",children:ua.map(f=>i.jsxs("button",{className:`settings-voice-btn ${!t.customVoiceId&&t.voiceId===f.id?"active":""}`,onClick:()=>{h("voiceId",f.id),h("customVoiceId","")},children:[i.jsx("span",{className:"voice-btn-label",children:f.label}),i.jsxs("span",{className:"voice-btn-meta",children:[f.lang," · ",f.gender," · ",f.style]})]},f.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:f=>h("customVoiceId",f.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:b,children:"重置为默认设置"})]})]})]})}tn.createRoot(document.getElementById("jbot-root")).render(i.jsx(l.StrictMode,{children:i.jsx(Sr,{basename:"/jbot",children:i.jsxs(er,{children:[i.jsx(Pe,{path:"/",element:i.jsx(wa,{})}),i.jsx(Pe,{path:"/history",element:i.jsx(Ea,{})}),i.jsx(Pe,{path:"/settings",element:i.jsx(Ra,{})})]})})}));
|