friend-assistant 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/BUILD.json
CHANGED
package/dist/friend.mjs
CHANGED
|
@@ -29025,7 +29025,7 @@ async function daemonCommand(args, io2, deps = realDeps) {
|
|
|
29025
29025
|
import crossSpawn5 from "cross-spawn";
|
|
29026
29026
|
var PACKAGE = "friend-assistant";
|
|
29027
29027
|
var real = {
|
|
29028
|
-
current: () => true ? "0.1.
|
|
29028
|
+
current: () => true ? "0.1.30" : "development",
|
|
29029
29029
|
latest: () => new Promise((resolve11) => {
|
|
29030
29030
|
const child = crossSpawn5("npm", ["view", PACKAGE, "version", "--prefer-online"], { stdio: ["ignore", "pipe", "ignore"] });
|
|
29031
29031
|
let out = "";
|
|
@@ -29313,7 +29313,7 @@ async function run(argv, io2) {
|
|
|
29313
29313
|
case "version":
|
|
29314
29314
|
case "--version":
|
|
29315
29315
|
case "-v":
|
|
29316
|
-
io2.out(true ? "0.1.
|
|
29316
|
+
io2.out(true ? "0.1.30" : "development");
|
|
29317
29317
|
return 0;
|
|
29318
29318
|
case "lan":
|
|
29319
29319
|
return await lanCommand(rest, io2);
|
|
@@ -4453,4 +4453,4 @@ ${e}</tr>
|
|
|
4453
4453
|
`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?`th`:`td`;return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
|
|
4454
4454
|
`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${IC(e,!0)}</code>`}br(e){return`<br>`}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,text:n,tokens:r,autolink:i}){let a=i?IC(n,!0):this.parser.parseInline(r),o=RC(e);if(o===null)return a;e=IC(o,i);let s=`<a href="`+e+`"`;return t&&(s+=` title="`+IC(t)+`"`),s+=`>`+a+`</a>`,s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=RC(e);if(i===null)return IC(n);e=i;let a=`<img src="${IC(e)}" alt="${IC(n)}"`;return t&&(a+=` title="${IC(t)}"`),a+=`>`,a}text(e){return`tokens`in e&&e.tokens?this.parser.parseInline(e.tokens):`escaped`in e&&e.escaped?e.text:IC(e.text)}},ZC=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return``+e}image({text:e}){return``+e}br(){return``}checkbox({raw:e}){return e}},QC=class e{options;renderer;textRenderer;constructor(e){this.options=e||fS,this.options.renderer=this.options.renderer||new XC,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new ZC}static parse(t,n){return new e(n).parse(t)}static parseInline(t,n){return new e(n).parseInline(t)}parse(e){this.renderer.parser=this;let t=``;for(let n=0;n<e.length;n++){let r=e[n];if(this.options.extensions?.renderers?.[r.type]){let e=r,n=this.options.extensions.renderers[e.type].call({parser:this},e);if(n!==!1||![`space`,`hr`,`heading`,`code`,`table`,`blockquote`,`list`,`checkbox`,`html`,`def`,`paragraph`,`text`].includes(e.type)){t+=n||``;continue}}let i=r;switch(i.type){case`space`:t+=this.renderer.space(i);break;case`hr`:t+=this.renderer.hr(i);break;case`heading`:t+=this.renderer.heading(i);break;case`code`:t+=this.renderer.code(i);break;case`table`:t+=this.renderer.table(i);break;case`blockquote`:t+=this.renderer.blockquote(i);break;case`list`:t+=this.renderer.list(i);break;case`checkbox`:t+=this.renderer.checkbox(i);break;case`html`:t+=this.renderer.html(i);break;case`def`:t+=this.renderer.def(i);break;case`paragraph`:t+=this.renderer.paragraph(i);break;case`text`:t+=this.renderer.text(i);break;default:{let e=`Token with "`+i.type+`" type was not found.`;if(this.options.silent)return console.error(e),``;throw Error(e)}}}return t}parseInline(e,t=this.renderer){this.renderer.parser=this;let n=``;for(let r=0;r<e.length;r++){let i=e[r];if(this.options.extensions?.renderers?.[i.type]){let e=this.options.extensions.renderers[i.type].call({parser:this},i);if(e!==!1||![`escape`,`html`,`link`,`image`,`checkbox`,`strong`,`em`,`codespan`,`br`,`del`,`text`].includes(i.type)){n+=e||``;continue}}let a=i;switch(a.type){case`escape`:n+=t.text(a);break;case`html`:n+=t.html(a);break;case`link`:n+=t.link(a);break;case`image`:n+=t.image(a);break;case`checkbox`:n+=t.checkbox(a);break;case`strong`:n+=t.strong(a);break;case`em`:n+=t.em(a);break;case`codespan`:n+=t.codespan(a);break;case`br`:n+=t.br(a);break;case`del`:n+=t.del(a);break;case`text`:n+=t.text(a);break;default:{let e=`Token with "`+a.type+`" type was not found.`;if(this.options.silent)return console.error(e),``;throw Error(e)}}}return n}},$C=class{options;block;constructor(e){this.options=e||fS}static passThroughHooks=new Set([`preprocess`,`postprocess`,`processAllTokens`,`emStrongMask`]);static passThroughHooksRespectAsync=new Set([`preprocess`,`postprocess`,`processAllTokens`]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(e=this.block){return e?YC.lex:YC.lexInline}provideParser(e=this.block){return e?QC.parse:QC.parseInline}},ew=new class{defaults=dS();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=QC;Renderer=XC;TextRenderer=ZC;Lexer=YC;Tokenizer=JC;Hooks=$C;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(let r of e)switch(n=n.concat(t.call(this,r)),r.type){case`table`:{let e=r;for(let r of e.header)n=n.concat(this.walkTokens(r.tokens,t));for(let r of e.rows)for(let e of r)n=n.concat(this.walkTokens(e.tokens,t));break}case`list`:{let e=r;n=n.concat(this.walkTokens(e.items,t));break}default:{let e=r;this.defaults.extensions?.childTokens?.[e.type]?this.defaults.extensions.childTokens[e.type].forEach(r=>{let i=e[r].flat(1/0);n=n.concat(this.walkTokens(i,t))}):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(e=>{let n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach(e=>{if(!e.name)throw Error(`extension name required`);if(`renderer`in e){let n=t.renderers[e.name];n?t.renderers[e.name]=function(...t){let r=e.renderer.apply(this,t);return r===!1&&(r=n.apply(this,t)),r}:t.renderers[e.name]=e.renderer}if(`tokenizer`in e){if(!e.level||e.level!==`block`&&e.level!==`inline`)throw Error(`extension level must be 'block' or 'inline'`);let n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&(e.level===`block`?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:e.level===`inline`&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}`childTokens`in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)}),n.extensions=t),e.renderer){let t=this.defaults.renderer||new XC(this.defaults);for(let n in e.renderer){if(!(n in t))throw Error(`renderer '${n}' does not exist`);if([`options`,`parser`].includes(n))continue;let r=n,i=e.renderer[r],a=t[r];t[r]=(...e)=>{let n=i.apply(t,e);return n===!1&&(n=a.apply(t,e)),n||``}}n.renderer=t}if(e.tokenizer){let t=this.defaults.tokenizer||new JC(this.defaults);for(let n in e.tokenizer){if(!(n in t))throw Error(`tokenizer '${n}' does not exist`);if([`options`,`rules`,`lexer`].includes(n))continue;let r=n,i=e.tokenizer[r],a=t[r];t[r]=(...e)=>{let n=i.apply(t,e);return n===!1&&(n=a.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){let t=this.defaults.hooks||new $C;for(let n in e.hooks){if(!(n in t))throw Error(`hook '${n}' does not exist`);if([`options`,`block`].includes(n))continue;let r=n,i=e.hooks[r],a=t[r];t[r]=$C.passThroughHooks.has(n)?e=>{if(this.defaults.async&&$C.passThroughHooksRespectAsync.has(n))return(async()=>{let n=await i.call(t,e);return a.call(t,n)})();let r=i.call(t,e);return a.call(t,r)}:(...e)=>{if(this.defaults.async)return(async()=>{let n=await i.apply(t,e);return n===!1&&(n=await a.apply(t,e)),n})();let n=i.apply(t,e);return n===!1&&(n=a.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){let t=this.defaults.walkTokens,r=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(r.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return YC.lex(e,t??this.defaults)}parser(e,t){return QC.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{let r={...n},i={...this.defaults,...r},a=this.onError(!!i.silent,!!i.async);if(this.defaults.async===!0&&r.async===!1)return a(Error(`marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.`));if(typeof t>`u`||t===null)return a(Error(`marked(): input parameter is undefined or null`));if(typeof t!=`string`)return a(Error(`marked(): input parameter is of type `+Object.prototype.toString.call(t)+`, string expected`));if(i.hooks&&(i.hooks.options=i,i.hooks.block=e),i.async)return(async()=>{let n=i.hooks?await i.hooks.preprocess(t):t,r=await(i.hooks?await i.hooks.provideLexer(e):e?YC.lex:YC.lexInline)(n,i),a=i.hooks?await i.hooks.processAllTokens(r):r;i.walkTokens&&await Promise.all(this.walkTokens(a,i.walkTokens));let o=await(i.hooks?await i.hooks.provideParser(e):e?QC.parse:QC.parseInline)(a,i);return i.hooks?await i.hooks.postprocess(o):o})().catch(a);try{i.hooks&&(t=i.hooks.preprocess(t));let n=(i.hooks?i.hooks.provideLexer(e):e?YC.lex:YC.lexInline)(t,i);i.hooks&&(n=i.hooks.processAllTokens(n)),i.walkTokens&&this.walkTokens(n,i.walkTokens);let r=(i.hooks?i.hooks.provideParser(e):e?QC.parse:QC.parseInline)(n,i);return i.hooks&&(r=i.hooks.postprocess(r)),r}catch(e){return a(e)}}}onError(e,t){return n=>{if(n.message+=`
|
|
4455
4455
|
Please report this to https://github.com/markedjs/marked.`,e){let e=`<p>An error occurred:</p><pre>`+IC(n.message+``,!0)+`</pre>`;return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}};function tw(e,t){return ew.parse(e,t)}tw.options=tw.setOptions=function(e){return ew.setOptions(e),tw.defaults=ew.defaults,pS(tw.defaults),tw},tw.getDefaults=dS,tw.defaults=fS;function nw(...e){return ew.use(...e),tw.defaults=ew.defaults,pS(tw.defaults),tw}tw.use=nw,tw.walkTokens=function(e,t){return ew.walkTokens(e,t)},tw.parseInline=ew.parseInline,tw.Parser=QC,tw.parser=QC.parse,tw.Renderer=XC,tw.TextRenderer=ZC,tw.Lexer=YC,tw.lexer=YC.lex,tw.Tokenizer=JC,tw.Hooks=$C,tw.parse=tw,tw.options,tw.setOptions,tw.walkTokens,tw.parseInline,QC.parse,YC.lex;var rw=!1;function iw(){rw||(rw=!0,uS.addHook(`afterSanitizeAttributes`,e=>{e instanceof Element&&e.tagName===`A`&&(e.setAttribute(`rel`,`noopener noreferrer`),e.setAttribute(`target`,`_blank`))}))}function aw(e){iw();let t=tw.parse(e,{async:!1,breaks:!0});return uS.sanitize(t,{ALLOWED_TAGS:[`p`,`br`,`strong`,`em`,`code`,`pre`,`ul`,`ol`,`li`,`a`,`h1`,`h2`,`h3`,`h4`,`h5`,`h6`,`blockquote`,`hr`,`del`,`table`,`thead`,`tbody`,`tr`,`th`,`td`],ALLOWED_ATTR:[`href`,`rel`,`target`],ALLOWED_URI_REGEXP:/^(?:https?:|mailto:)/i})}var ow=e=>Number.isFinite(e);function sw(e){let t=Math.floor(Math.log10(e)),n=e/10**t;return(n<=1?1:n<=2?2:n<=2.5?2.5:n<=5?5:10)*10**t}function cw(e,t,n=5){let r=ow(e)?e:0,i=ow(t)?t:r+1;r>i&&([r,i]=[i,r]),r===i&&(i=r+(Math.abs(r)||1));let a=sw((i-r)/Math.max(1,n-1)),o=Math.floor(r/a)*a,s=Math.ceil(i/a)*a,c=[];for(let e=o;e<=s+a/2;e+=a)c.push(Math.round(e*1e9)/1e9);return{min:o,max:s,ticks:c}}function lw(e,t){let[n,r]=e,[i,a]=t;return r===n?()=>i:e=>i+(e-n)/(r-n)*(a-i)}function uw(e){return e.map(([e,t],n)=>`${n===0?`M`:`L`}${e.toFixed(2)} ${t.toFixed(2)}`).join(` `)}function dw(e,t,n,r,i){let a=r=>{let i=r*Math.PI/180;return`${(e+n*Math.cos(i)).toFixed(2)} ${(t+n*Math.sin(i)).toFixed(2)}`},o=+(Math.abs(i-r)>180);return`M ${a(r)} A ${n} ${n} 0 ${o} 1 ${a(i)}`}function fw(e,t,n){return!ow(e)||!ow(t)||!ow(n)||n<=t?0:Math.min(1,Math.max(0,(e-t)/(n-t)))*240}function pw(e,t,n,r){let i=t.x-e.x,a=t.y-e.y,o=Math.hypot(i,a);if(o===0||o<=n+r)return{from:{...e},to:{...t}};let s=i/o,c=a/o;return{from:{x:e.x+s*n,y:e.y+c*n},to:{x:t.x-s*r,y:t.y-c*r}}}function mw(e,t,n){if(e<=0)return[];if(e===1)return[{x:t/2,y:n/2}];let r=Math.min(t,n)*.36;return Array.from({length:e},(i,a)=>{let o=-Math.PI/2+a*2*Math.PI/e;return{x:t/2+r*Math.cos(o),y:n/2+r*Math.sin(o)}})}var hw=e=>typeof e==`object`&&!!e&&!Array.isArray(e),gw=e=>typeof e==`string`?e:typeof e==`number`?String(e):``,_w=e=>Array.isArray(e)?e:[],vw=e=>typeof e==`number`?Number.isFinite(e)?e:null:typeof e==`string`&&e.trim()!==``&&Number.isFinite(Number(e))?Number(e):null,yw=(e,t)=>e.length>t?e.slice(0,t)+`…`:e,bw=[`var(--accent)`,`#ffb454`,`#7b8cff`,`#5ef0b0`,`#ff6b7a`,`#c792ea`],xw=({text:e})=>e?(0,p.jsx)(`h3`,{className:`obj-title`,children:e}):null,Sw=({text:e=`No data`})=>(0,p.jsx)(`p`,{className:`obj-empty`,children:e}),Cw=400,ww=220,Tw={l:44,r:12,t:10,b:28};function Ew({props:e}){let t=e.kind===`bar`||e.kind===`area`?e.kind:`line`,n=_w(e.labels).slice(0,120).map(gw),r=_w(e.series).slice(0,6).map((e,t)=>{let n=hw(e)?e:{},r=_w(n.values).slice(0,120).map((e,t)=>({idx:t,v:vw(e)})).filter(e=>e.v!==null);return{name:gw(n.name)||`series ${t+1}`,points:r}}).filter(e=>e.points.length>0);if(r.length===0)return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsx)(Sw,{})]});let i=r.flatMap(e=>e.points.map(e=>e.v)),a=Math.min(...i),o=Math.max(...i),s=cw(t===`line`?a:Math.min(0,a),t===`line`?o:Math.max(0,o),5),c=Math.max(n.length,...r.map(e=>e.points[e.points.length-1].idx+1),2),l=lw([s.min,s.max],[ww-Tw.b,Tw.t]),u=lw([0,c-1],[Tw.l,Cw-Tw.r]),d=(Cw-Tw.l-Tw.r)/c,f=Math.max(1,d*.7/r.length),m=(e,t)=>Tw.l+e*d+d*.15+t*f,h=Math.max(1,Math.ceil(c/6)),g=gw(e.unit);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsxs)(`svg`,{className:`obj-chart`,viewBox:`0 0 ${Cw} ${ww}`,role:`img`,"aria-label":gw(e.title)||`chart`,children:[s.ticks.map(e=>(0,p.jsxs)(`g`,{children:[(0,p.jsx)(`line`,{className:`grid`,x1:Tw.l,x2:Cw-Tw.r,y1:l(e),y2:l(e)}),(0,p.jsxs)(`text`,{className:`tick`,x:Tw.l-6,y:l(e)+3,textAnchor:`end`,children:[e,g&&e===s.max?g:``]})]},e)),Array.from({length:c},(e,t)=>t).filter(e=>e%h===0&&n[e]).map(e=>(0,p.jsx)(`text`,{className:`tick`,x:t===`bar`?m(e,0)+f*r.length/2:u(e),y:212,textAnchor:`middle`,children:yw(n[e],8)},e)),r.map((e,n)=>{let r=bw[n%bw.length];if(t===`bar`)return(0,p.jsx)(`g`,{children:e.points.map(e=>(0,p.jsx)(`rect`,{className:`bar`,x:m(e.idx,n),y:Math.min(l(e.v),l(0)),width:f,height:Math.abs(l(e.v)-l(0)),fill:r},e.idx))},n);let i=e.points.map(e=>[u(e.idx),l(e.v)]),a=uw(i),o=`${a} L${i[i.length-1][0].toFixed(2)} ${l(s.min).toFixed(2)} L${i[0][0].toFixed(2)} ${l(s.min).toFixed(2)} Z`;return(0,p.jsxs)(`g`,{children:[t===`area`&&(0,p.jsx)(`path`,{className:`series-area`,d:o,fill:r,opacity:.18}),(0,p.jsx)(`path`,{className:`series-line`,d:a,fill:`none`,stroke:r,strokeWidth:2,strokeLinejoin:`round`})]},n)})]}),r.length>1&&(0,p.jsx)(`ul`,{className:`legend`,children:r.map((e,t)=>(0,p.jsxs)(`li`,{children:[(0,p.jsx)(`i`,{style:{background:bw[t%bw.length]}}),(0,p.jsx)(`span`,{children:e.name})]},t))})]})}function Dw({props:e}){let t=vw(e.min)??0,n=vw(e.max)??100,r=vw(e.value)??t,i=fw(r,t,n),a=i/240;return(0,p.jsxs)(`div`,{className:`obj-gauge ${a>.95?`gauge-crit`:a>.8?`gauge-warn`:``}`,children:[(0,p.jsxs)(`svg`,{viewBox:`0 0 200 150`,role:`img`,"aria-label":`${gw(e.label)} ${r}`,children:[(0,p.jsx)(`path`,{className:`track`,d:dw(100,100,70,150,390),fill:`none`,strokeWidth:12,strokeLinecap:`round`}),i>0&&(0,p.jsx)(`path`,{className:`value`,d:dw(100,100,70,150,150+i),fill:`none`,strokeWidth:12,strokeLinecap:`round`})]}),(0,p.jsxs)(`div`,{className:`gauge-read`,children:[(0,p.jsx)(`span`,{className:`gauge-value`,children:String(Math.round(r*100)/100)}),gw(e.unit)&&(0,p.jsx)(`small`,{className:`gauge-unit`,children:gw(e.unit)})]}),(0,p.jsx)(`span`,{className:`obj-label`,children:gw(e.label)})]})}function Ow({props:e}){let t=_w(e.items).slice(0,30).map(e=>hw(e)?e:{}).map(e=>({time:gw(e.time),title:gw(e.title),detail:gw(e.detail)})).filter(e=>e.title||e.time);return t.length===0?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsx)(Sw,{text:`Nothing to show`})]}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsx)(`ol`,{className:`obj-timeline`,children:t.map((e,t)=>(0,p.jsxs)(`li`,{children:[(0,p.jsx)(`time`,{children:e.time}),(0,p.jsx)(`strong`,{children:e.title}),e.detail&&(0,p.jsx)(`span`,{children:e.detail})]},t))})]})}var kw=400,Aw=300,jw=12;function Mw({props:e}){let t=(0,l.useId)(),n=new Set,r=[];for(let t of _w(e.nodes)){let e=hw(t)?t:{},i=gw(e.id);if(i&&!n.has(i)&&(n.add(i),r.push({id:i,label:gw(e.label)||i}),r.length>=40))break}if(r.length===0)return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsx)(Sw,{text:`Nothing to show`})]});let i=new Map(r.map((e,t)=>[e.id,mw(r.length,kw,Aw)[t]])),a=[];for(let t of _w(e.edges)){let e=hw(t)?t:{},n=gw(e.from),r=gw(e.to);if(i.has(n)&&i.has(r)&&n!==r&&(a.push({from:n,to:r,label:gw(e.label)}),a.length>=80))break}return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(xw,{text:gw(e.title)}),(0,p.jsxs)(`svg`,{className:`obj-graph`,viewBox:`0 0 ${kw} ${Aw}`,role:`img`,"aria-label":gw(e.title)||`graph`,children:[(0,p.jsx)(`defs`,{children:(0,p.jsx)(`marker`,{id:t,viewBox:`0 0 10 10`,refX:`9`,refY:`5`,markerWidth:`6`,markerHeight:`6`,orient:`auto-start-reverse`,children:(0,p.jsx)(`path`,{d:`M0 0 L10 5 L0 10 z`,className:`arrow`})})}),a.map((e,n)=>{let{from:r,to:a}=pw(i.get(e.from),i.get(e.to),14,17),o=(r.x+a.x)/2+(kw/2-(r.x+a.x)/2)*.25,s=(r.y+a.y)/2+(Aw/2-(r.y+a.y)/2)*.25;return(0,p.jsxs)(`g`,{children:[(0,p.jsx)(`path`,{className:`edge`,d:`M ${r.x.toFixed(1)} ${r.y.toFixed(1)} Q ${o.toFixed(1)} ${s.toFixed(1)} ${a.x.toFixed(1)} ${a.y.toFixed(1)}`,fill:`none`,markerEnd:`url(#${t})`}),e.label&&(0,p.jsx)(`text`,{className:`edge-label`,x:o,y:s,textAnchor:`middle`,children:yw(e.label,12)})]},n)}),r.map(e=>{let t=i.get(e.id);return(0,p.jsxs)(`g`,{children:[(0,p.jsx)(`circle`,{className:`node`,cx:t.x,cy:t.y,r:jw}),(0,p.jsx)(`text`,{className:`node-label`,x:t.x,y:t.y+26,textAnchor:`middle`,children:yw(e.label,18)})]},e.id)})]})]})}var Nw=e=>typeof e==`string`?e:typeof e==`number`?String(e):``,Pw=e=>Array.isArray(e)?e:[],Fw=e=>typeof e==`object`&&e?e:{},Iw=/^\/api\/media\/[0-9a-f]{32}$/,Lw=e=>typeof e==`string`&&Iw.test(e)?e:null,Rw=({props:e})=>Nw(e.title)?(0,p.jsx)(`h3`,{className:`obj-title`,children:Nw(e.title)}):null;function zw({props:e}){let t=(0,l.useMemo)(()=>aw(Nw(e.text)),[e.text]);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(Rw,{props:e}),(0,p.jsx)(`div`,{className:`obj-md obj-doc`,dangerouslySetInnerHTML:{__html:t}})]})}function Bw({props:e}){let t=Math.min(100,Math.max(0,Number(e.value)||0));return(0,p.jsxs)(`div`,{className:`obj-progress`,children:[(0,p.jsxs)(`div`,{className:`obj-progress-head`,children:[(0,p.jsx)(`span`,{className:`obj-label`,children:Nw(e.label)}),(0,p.jsxs)(`span`,{className:`obj-progress-pct`,children:[Math.round(t),`%`]})]}),(0,p.jsx)(`div`,{className:`obj-progress-bar`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(t),"aria-label":Nw(e.label)||`Progress`,children:(0,p.jsx)(`i`,{style:{width:`${t}%`}})}),Nw(e.detail)&&(0,p.jsx)(`span`,{className:`obj-progress-detail`,children:Nw(e.detail)})]})}function Vw({props:e}){let t=Pw(e.items).map(e=>Fw(typeof e==`object`&&e?e:{text:e})),n=t.filter(e=>e.done===!0).length;return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(Rw,{props:e}),(0,p.jsx)(`ul`,{className:`obj-checklist`,children:t.map((e,t)=>(0,p.jsxs)(`li`,{className:e.done===!0?`done`:void 0,children:[(0,p.jsx)(`span`,{className:`box`,"aria-hidden":`true`,children:e.done===!0?`✓`:``}),(0,p.jsx)(`span`,{children:Nw(e.text)})]},t))}),t.length>0&&(0,p.jsxs)(`small`,{className:`obj-progress-detail`,children:[n,` of `,t.length,` done`]})]})}function Hw({props:e}){return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(Rw,{props:e}),(0,p.jsx)(`dl`,{className:`obj-kv`,children:Pw(e.rows).map((e,t)=>{let n=Fw(e);return(0,p.jsxs)(`div`,{children:[(0,p.jsx)(`dt`,{children:Nw(n.key)}),(0,p.jsx)(`dd`,{children:Nw(n.value)})]},t)})})]})}var Uw=e=>String(Math.floor(e)).padStart(2,`0`);function Ww(e){let t=Math.max(0,Math.ceil(e));return`${Uw(t/3600)}:${Uw(t%3600/60)}:${Uw(t%60)}`}function Gw({props:e}){let t=(0,l.useRef)(null);if(t.current===null){let n=typeof e.to==`string`?Date.parse(e.to):NaN,r=Number(e.seconds);t.current=Number.isFinite(n)?n:Date.now()+(Number.isFinite(r)?r:0)*1e3}let[n,r]=(0,l.useState)(Date.now());(0,l.useEffect)(()=>{let e=setInterval(()=>r(Date.now()),250);return()=>clearInterval(e)},[]);let i=(t.current-n)/1e3;return(0,p.jsxs)(`div`,{className:`obj-countdown${i<=0?` done`:``}`,children:[(0,p.jsx)(`span`,{className:`obj-label`,children:Nw(e.title)||Nw(e.label)}),(0,p.jsx)(`span`,{className:`obj-countdown-time`,role:`timer`,children:Ww(i)})]})}function Kw({props:e}){let t=Lw(e.src);return(0,p.jsxs)(`div`,{className:`obj-media`,children:[(0,p.jsx)(Rw,{props:e}),t?(0,p.jsx)(`img`,{src:t,alt:Nw(e.title)||`Picture`,loading:`lazy`}):(0,p.jsx)(`p`,{className:`obj-empty`,children:`This picture is not available.`})]})}function qw({props:e}){let t=Lw(e.src);return(0,p.jsxs)(`div`,{className:`obj-media`,children:[(0,p.jsx)(Rw,{props:e}),t?(0,p.jsx)(`video`,{src:t,controls:!0,playsInline:!0,preload:`metadata`,"aria-label":Nw(e.title)||`Video`}):(0,p.jsx)(`p`,{className:`obj-empty`,children:`This clip is not available.`})]})}function Jw({props:e}){let t=Lw(e.src);return(0,p.jsxs)(`div`,{className:`obj-media obj-pdf`,children:[(0,p.jsx)(Rw,{props:e}),t?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`iframe`,{src:t,title:Nw(e.title)||`Document`}),(0,p.jsx)(`a`,{className:`obj-open`,href:t,target:`_blank`,rel:`noopener noreferrer`,children:`Open in a new tab`})]}):(0,p.jsx)(`p`,{className:`obj-empty`,children:`This document is not available.`})]})}function Yw({props:e}){let t=Pw(e.items).map(Fw).filter(e=>Lw(e.src)),[n,r]=(0,l.useState)(0),i=Math.min(n,Math.max(0,t.length-1)),a=t[i];if(!a)return(0,p.jsx)(`p`,{className:`obj-empty`,children:`Nothing to show.`});let o=Lw(a.src),s=a.kind===`video`;return(0,p.jsxs)(`div`,{className:`obj-media obj-gallery`,children:[(0,p.jsx)(Rw,{props:e}),s?(0,p.jsx)(`video`,{src:o,controls:!0,playsInline:!0,preload:`metadata`},o):(0,p.jsx)(`img`,{src:o,alt:Nw(a.caption)||`Picture ${i+1}`},o),(0,p.jsxs)(`div`,{className:`obj-gallery-bar`,children:[(0,p.jsx)(`button`,{type:`button`,"aria-label":`Previous`,disabled:t.length<2,onClick:()=>r((i+t.length-1)%t.length),children:`‹`}),(0,p.jsxs)(`span`,{children:[Nw(a.caption),(0,p.jsxs)(`small`,{children:[i+1,` / `,t.length]})]}),(0,p.jsx)(`button`,{type:`button`,"aria-label":`Next`,disabled:t.length<2,onClick:()=>r((i+1)%t.length),children:`›`})]})]})}var Xw=[`default-src 'none'`,`script-src 'unsafe-inline'`,`style-src 'unsafe-inline'`,`img-src data: blob:`,`form-action 'none'`,`base-uri 'none'`].join(`; `),Zw=`html,body{margin:0;min-height:100%;background:#050b10;color:var(--ink,#d8f6ff);font:15px/1.5 var(--ui,system-ui,sans-serif)}`,Qw=[`--accent`,`--ink`,`--muted`,`--ok`,`--warn`,`--bad`,`--glass`,`--edge`,`--ui`,`--mono`],$w=/^[\w\s#().,%'"/-]+$/;function eT(){if(typeof document>`u`)return``;let e=getComputedStyle(document.documentElement),t=Qw.map(t=>[t,e.getPropertyValue(t).trim()]).filter(([,e])=>e&&$w.test(e));return t.length?`:root{${t.map(([e,t])=>`${e}:${t}`).join(`;`)}}`:``}function tT(e,t=``){return`<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="${Xw}"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${t}${Zw}</style></head><body>${e}</body></html>`}function nT({props:e}){let t=typeof e.html==`string`?e.html:``,n=typeof e.title==`string`?e.title:``,r=(0,l.useMemo)(()=>tT(t,eT()),[t]);return(0,p.jsxs)(`div`,{className:`obj-sandbox`,children:[n&&(0,p.jsx)(`h3`,{className:`obj-title`,children:n}),(0,p.jsx)(`iframe`,{title:n||`Page made by Friend`,sandbox:`allow-scripts`,referrerPolicy:`no-referrer`,allow:``,srcDoc:r})]})}var rT=e=>typeof e==`string`?e:typeof e==`number`?String(e):``,iT=e=>Array.isArray(e)?e:[];function aT({props:e}){let t=(0,l.useMemo)(()=>aw(rT(e.text)),[e.text]);return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`div`,{className:`obj-md`,dangerouslySetInnerHTML:{__html:t}})]})}function oT({props:e}){return(0,p.jsxs)(`div`,{className:`obj-stat`,children:[(0,p.jsx)(`span`,{className:`obj-label`,children:rT(e.label)}),(0,p.jsxs)(`span`,{className:`obj-value`,children:[(0,p.jsx)(`span`,{children:rT(e.value)}),rT(e.unit)&&(0,p.jsx)(`small`,{children:rT(e.unit)})]}),rT(e.delta)&&(0,p.jsx)(`span`,{className:`obj-delta`,children:rT(e.delta)})]})}function sT({props:e}){return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`ul`,{className:`obj-list`,children:iT(e.items).map((e,t)=>{let n=typeof e==`object`&&e?e:{text:e};return(0,p.jsx)(`li`,{className:n.done?`done`:void 0,children:rT(n.text)},t)})})]})}function cT({props:e}){let t=iT(e.columns),n=iT(e.rows);return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`div`,{className:`obj-table-wrap`,children:(0,p.jsxs)(`table`,{className:`obj-table`,children:[(0,p.jsx)(`thead`,{children:(0,p.jsx)(`tr`,{children:t.map((e,t)=>(0,p.jsx)(`th`,{children:rT(e)},t))})}),(0,p.jsx)(`tbody`,{children:n.map((e,t)=>(0,p.jsx)(`tr`,{children:iT(e).map((e,t)=>(0,p.jsx)(`td`,{children:rT(e)},t))},t))})]})})]})}function lT({props:e}){return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`pre`,{className:`obj-code`,"data-lang":rT(e.language),children:(0,p.jsx)(`code`,{children:rT(e.code)})})]})}function uT({part:e}){let t=typeof e==`object`&&e?e:{},n=typeof t.type==`string`?t.type:``;if(n===`group`||n===`tabs`||n===`sandbox`)return null;let r=pT[n];return r?(0,p.jsx)(`div`,{className:`obj-part obj-part-${n}`,children:(0,p.jsx)(r,{props:typeof t.props==`object`&&t.props!==null?t.props:{}})}):null}function dT({props:e}){let t=e.layout===`row`||e.layout===`column`?e.layout:`grid`;return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`div`,{className:`obj-group obj-group-${t}`,children:iT(e.items).map((e,t)=>(0,p.jsx)(uT,{part:e},t))})]})}function fT({props:e}){let t=iT(e.tabs).map(e=>typeof e==`object`&&e?e:{}),[n,r]=(0,l.useState)(0),i=Math.min(n,Math.max(0,t.length-1));return(0,p.jsxs)(p.Fragment,{children:[rT(e.title)&&(0,p.jsx)(`h3`,{className:`obj-title`,children:rT(e.title)}),(0,p.jsx)(`div`,{className:`obj-tabs`,role:`tablist`,children:t.map((e,t)=>(0,p.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":t===i,className:t===i?`on`:void 0,onClick:()=>r(t),children:rT(e.title)||`Tab ${t+1}`},t))}),t[i]&&(0,p.jsx)(uT,{part:t[i]})]})}var pT={card:aT,stat:oT,list:sT,table:cT,code:lT,chart:Ew,gauge:Dw,timeline:Ow,graph:Mw,sandbox:nT,markdown:zw,image:Kw,video:qw,pdf:Jw,gallery:Yw,group:dT,tabs:fT,progress:Bw,checklist:Vw,countdown:Gw,kv:Hw};function mT(e,t){let n=new Map(t.map(e=>[e.id,e])),r=[],i=new Set;for(let t of e){if(i.has(t.object.id))continue;i.add(t.object.id);let e=n.get(t.object.id);r.push(e?{object:e,leaving:!1}:{object:t.object,leaving:!0})}for(let e of t)i.has(e.id)||(i.add(e.id),r.push({object:e,leaving:!1}));return r}function hT(e,t){let[n,r]=(0,l.useState)(()=>e.map(e=>({object:e,leaving:!1}))),i=(0,l.useRef)(new Map);return(0,l.useEffect)(()=>{r(n=>{let a=mT(n,e),o=new Set(n.filter(e=>e.leaving).map(e=>e.object.id));for(let e of a){let n=i.current.get(e.object.id);if(!e.leaving)n&&clearTimeout(n),i.current.delete(e.object.id);else if(!o.has(e.object.id)&&!n){let n=e.object.id;i.current.set(n,setTimeout(()=>{i.current.delete(n),r(e=>e.filter(e=>!(e.object.id===n&&e.leaving)))},Math.max(t,0)))}}return t<=0?a.filter(e=>!e.leaving):a})},[e,t]),(0,l.useEffect)(()=>()=>{for(let e of i.current.values())clearTimeout(e);i.current.clear()},[]),n}var gT=.12,_T=.1,vT=.02,yT=(e,t,n)=>Math.min(Math.max(e,t),n);function bT(e){let t=yT(e.w,gT,1),n=yT(e.h,_T,1);return{x:yT(e.x,0,1-t),y:yT(e.y,0,1-n),w:t,h:n}}function xT(e,t){let n=t.getBoundingClientRect(),r=e.getBoundingClientRect();return n.width<=0||n.height<=0?null:bT({x:(r.left-n.left)/n.width,y:(r.top-n.top)/n.height,w:r.width/n.width,h:r.height/n.height})}function ST(e,t,n){let r=(0,l.useRef)(null),[i,a]=(0,l.useState)(null),o=(0,l.useCallback)((n,r)=>{let i=bT(r);t({type:`object.place`,id:n,placement:{x:i.x,y:i.y,w:i.w,h:i.h}}),e({type:`stage.move`,objectId:n,rect:i})},[e,t]),s=(0,l.useCallback)((e,t,i)=>{if(e.pointerType===`mouse`&&e.button!==0)return;let o=n(),s=e.currentTarget.closest(`[data-object]`);if(!o||!s||r.current)return;let c=xT(s,o);if(!c)return;let l=o.getBoundingClientRect();r.current={id:t.id,mode:i,pointer:e.pointerId,startX:e.clientX,startY:e.clientY,from:c,stageW:l.width,stageH:l.height};try{e.currentTarget.setPointerCapture(e.pointerId)}catch{}e.stopPropagation(),e.preventDefault(),a({id:t.id,box:c})},[n]),c=(e,t)=>{let n=(t.clientX-e.startX)/e.stageW,r=(t.clientY-e.startY)/e.stageH;return e.mode===`move`?bT({...e.from,x:e.from.x+n,y:e.from.y+r}):bT({...e.from,w:e.from.w+n,h:e.from.h+r})};return{preview:i,begin:s,move:(0,l.useCallback)(e=>{let t=r.current;t&&t.pointer===e.pointerId&&a({id:t.id,box:c(t,e)})},[]),end:(0,l.useCallback)((e,t)=>{let n=r.current;n&&n.pointer===e.pointerId&&(r.current=null,a(null),t||o(n.id,c(n,e)))},[o]),key:(0,l.useCallback)((e,t)=>{let r={ArrowLeft:[-.02,0],ArrowRight:[vT,0],ArrowUp:[0,-.02],ArrowDown:[0,vT]}[e.key],i=n(),a=e.currentTarget.closest(`[data-object]`);if(!r||!i||!a)return;let s=xT(a,i);s&&(e.preventDefault(),o(t.id,e.shiftKey?{...s,w:s.w+r[0],h:s.h+r[1]}:{...s,x:s.x+r[0],y:s.y+r[1]}))},[o,n])}}function CT(e,t){if(e===`auto`)return{position:`relative`};if(t.w<600)return{position:`relative`,width:`100%`};let[n,r,i,a]=typeof e==`string`?Nl[e]:[e.x*100,e.y*100,e.w*100,e.h*100],o={position:`absolute`,left:`${n}%`,top:`${r}%`,width:`${i}%`};return e===`top`||e===`bottom`?{...o,maxHeight:`${a}%`}:{...o,height:`${a}%`}}var wT=350,TT=()=>typeof matchMedia==`function`&&matchMedia(`(prefers-reduced-motion: reduce)`).matches,ET=class extends l.Component{state={failed:!1};static getDerivedStateFromError(){return{failed:!0}}render(){return this.state.failed?null:this.props.children}};function DT(){let e=()=>({w:window.innerWidth,h:window.innerHeight}),[t,n]=(0,l.useState)(e);return(0,l.useEffect)(()=>{let t=()=>n(e());return window.addEventListener(`resize`,t),()=>window.removeEventListener(`resize`,t)},[]),t}var OT=350;function kT({state:e,send:t,dispatch:n,voice:r,slash:i,onMenu:a}){let o=DT(),[s,c]=(0,l.useState)(0),[u,d]=(0,l.useState)(!1),f=ne(),m=o.w<600,h=e.scene===`focus`||e.scene===`multi`,g={"--accent":e.mood.accent,"--intensity":e.mood.intensity},_=e.voice.mode,v=_===`listening`?`listening`:_===`speaking`?`speaking`:_===`transcribing`?`thinking`:e.presence.state,y=pb(e.look.reactivity),b=Math.min(1,(_===`listening`||_===`speaking`?e.voice.level:e.presence.amplitude)*y),x=(0,l.useRef)({timer:null,down:!1,talking:!1,id:null}),S=e=>{if(!(e.target===e.currentTarget||e.target.closest(`[data-presence]`))||e.pointerType===`mouse`&&e.button!==0)return;let t=x.current;if(!(t.down&&t.id!==null&&e.pointerId!==t.id)){t.timer&&clearTimeout(t.timer),t.down=!0,t.talking=!1,t.id=typeof e.pointerId==`number`?e.pointerId:null;try{t.id!==null&&e.currentTarget.setPointerCapture?.(t.id)}catch{}t.timer=r?setTimeout(()=>{t.down&&(t.talking=!0,r.pressStart())},OT):null}},C=(e,t)=>{let n=x.current;n.down&&(n.id===null||typeof e.pointerId!=`number`||e.pointerId===n.id)&&(n.down=!1,n.id=null,n.timer&&clearTimeout(n.timer),n.timer=null,n.talking?(n.talking=!1,t?r?.blur?.():r?.pressEnd()):t||c(e=>e+1))},w=(0,l.useRef)(null),T=ST(t,n,()=>w.current),E=hT(e.objects,TT()?0:wT),D=E.filter(e=>e.object.layer===`overlay`),O=E.filter(e=>e.object.layer!==`overlay`&&e.object.placement===`auto`),k=E.filter(e=>e.object.layer!==`overlay`&&e.object.placement!==`auto`),A=({object:e,leaving:r})=>{let i=pT[e.type];if(!i)return null;let a=e.layer===`overlay`,s=!m&&!r&&!a,c=T.preview?.id===e.id?T.preview.box:null,l=c?{x:c.x,y:c.y,w:c.w,h:c.h}:e.placement;return(0,p.jsxs)(`section`,{"data-object":e.id,className:`obj glass${e.style===`alert`?` alert`:``}${a?` overlay`:``}${e.pinned?` pinned`:``}${c?` dragging`:``}${r?` leaving`:``}`,style:a?void 0:CT(l,o),children:[s&&(0,p.jsx)(`div`,{className:`obj-grip`,role:`button`,tabIndex:0,"aria-label":`Move ${e.id}. Drag, or use the arrow keys; hold Shift to resize.`,onPointerDown:t=>T.begin(t,e,`move`),onPointerMove:T.move,onPointerUp:e=>T.end(e,!1),onPointerCancel:e=>T.end(e,!0),onKeyDown:t=>T.key(t,e)}),!a&&(0,p.jsx)(`button`,{className:`obj-pin${e.pinned?` on`:``}`,"aria-label":e.pinned?`Unpin ${e.id}`:`Pin ${e.id} to the screen`,"aria-pressed":!!e.pinned,title:e.pinned?`Pinned: stays on the screen. Click to unpin.`:`Pin: keep this on the screen.`,disabled:r,onClick:()=>t({type:`stage.pin`,objectId:e.id,pinned:!e.pinned}),children:(0,p.jsx)(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:e.pinned?`currentColor`:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:(0,p.jsx)(`path`,{d:`M12 17v5M9 3h6l-1 7 3 3H7l3-3-1-7z`})})}),(0,p.jsx)(`button`,{className:`obj-close`,"aria-label":`Dismiss ${e.id}`,title:e.pinned?`Remove this widget`:`Dismiss`,disabled:r,onClick:()=>{t({type:`stage.event`,objectId:e.id,event:`dismiss`}),n({type:`object.dismiss`,id:e.id})},children:`×`}),s&&(0,p.jsx)(`div`,{className:`obj-resize`,"aria-hidden":`true`,onPointerDown:t=>T.begin(t,e,`resize`),onPointerMove:T.move,onPointerUp:e=>T.end(e,!1),onPointerCancel:e=>T.end(e,!0)}),(0,p.jsx)(ET,{children:(0,p.jsx)(i,{props:e.props})})]},e.id)};return(0,p.jsxs)(`div`,{ref:w,"data-testid":`stage`,className:`stage`,style:g,onPointerDown:S,onPointerUp:e=>C(e,!1),onPointerCancel:e=>C(e,!0),onContextMenu:e=>r&&e.preventDefault(),children:[e.look.ambient&&(0,p.jsx)(`div`,{className:`ambient`,"aria-hidden":`true`,style:{opacity:.35+.65*e.mood.intensity}}),(0,p.jsx)(fb,{state:v,amplitude:b,pulse:e.presence.pulse,mode:h?`corner`:`full`,accent:e.mood.accent,style:e.presence.style,intensity:e.mood.intensity,scale:e.look.size}),(0,p.jsxs)(`div`,{className:m?`objects objects-stack`:`objects`,style:{zIndex:10},children:[O.length>0&&(0,p.jsx)(`div`,{className:`auto-grid`,children:O.map(A)}),k.map(A)]}),D.length>0&&(0,p.jsxs)(`div`,{className:`overlay-layer`,"data-testid":`overlay`,children:[(0,p.jsx)(`div`,{className:`overlay-backdrop`,onClick:()=>D.forEach(({object:e})=>{t({type:`stage.event`,objectId:e.id,event:`dismiss`}),n({type:`object.dismiss`,id:e.id})})}),D.map(A)]}),e.look.captions&&e.captions&&(0,p.jsx)(`p`,{className:`captions captions-${e.look.captionSize}${e.captionDone?` done`:``}`,"aria-live":`polite`,children:e.captions}),f&&r&&!u&&(0,p.jsx)(Fb,{voice:r,mode:_,onType:()=>c(e=>e+1),onMenu:()=>a?.()}),(0,p.jsx)(Mb,{requestOpen:s,slash:i,onOpenChange:d,onSend:e=>t({type:`chat.send`,text:e})})]})}function AT(){let e=()=>Math.random().toString(36).slice(2,12)+Date.now().toString(36);try{let t=sessionStorage.getItem(`friend.tab`);return t||(t=e(),sessionStorage.setItem(`friend.tab`,t)),t}catch{return e()}}function jT(){return`${location.protocol===`https:`?`wss`:`ws`}://${location.host}/ws`}function MT(e=jT()){let t=null,n=`connecting`,r=!1,i=0,a=!1,o=AT(),s=null,c=new Set,l=new Set,u=e=>{n=e,l.forEach(t=>t(e))};function d(){if(r)return;u(`connecting`);let n=new WebSocket(`${e}${e.includes(`?`)?`&`:`?`}tab=${o}${a?`&takeover=1`:``}`);t=n,n.onopen=()=>{i=0,a=!1,u(`open`)},n.onmessage=e=>{try{let t=JSON.parse(String(e.data));c.forEach(e=>e(t))}catch{}},n.onclose=e=>{if(!r){if(e.code===4401)return u(`unauthorized`);if(e.code===4409||e.code===4410)return u(`elsewhere`);u(`closed`),s=setTimeout(d,Math.min(500*2**i++,8e3))}},n.onerror=()=>{}}return d(),{send(e){t?.readyState===WebSocket.OPEN&&t.send(JSON.stringify(e))},onMessage(e){return c.add(e),()=>c.delete(e)},onState(e){return l.add(e),()=>l.delete(e)},state:()=>n,takeOver(){r||n!==`elsewhere`||(a=!0,i=0,d())},close(){r=!0,s&&clearTimeout(s),t?.close()}}}var NT={scene:`conversation`,objects:[],captions:``,captionDone:!0,presence:{state:`idle`,style:`sphere`,amplitude:0,pulse:0},mood:{accent:`#3fd8ff`,intensity:.6},approval:null,alerts:[],connection:`connecting`,chat:[],chatLive:!1,view:`companion`,look:{size:1,reactivity:.7,ambient:!0,captions:!0,captionSize:`medium`},viewKnown:!1,busy:!1,activity:null,deviceOnline:!1,voice:{mode:`idle`,level:0,available:!1,enrolled:!1},challenge:null,camera:{enabled:!1,stream:null},speaker:null,ownerName:``,assistantName:``,hud:null,music:null,musicCmd:null,uiOpen:null},PT=200,FT=e=>e.length>PT?e.slice(-200):e,IT=0,LT=e=>Math.min(1,Math.max(0,e));function RT(e,t){switch(t.cmd){case`scene`:return{...e,scene:t.mode};case`show`:{let n=e.objects.findIndex(e=>e.id===t.object.id),r=n===-1?[...e.objects,t.object]:e.objects.map((e,r)=>r===n?t.object:e);return{...e,objects:r}}case`update`:return{...e,objects:e.objects.map(e=>e.id===t.id?{...e,props:{...e.props,...t.props}}:e)};case`hide`:return{...e,objects:e.objects.filter(e=>e.id!==t.id)};case`clear`:return{...e,objects:e.objects.filter(e=>e.pinned),scene:`conversation`};case`pin`:return{...e,objects:e.objects.map(e=>e.id===t.id?{...e,pinned:!0}:e)};case`unpin`:return{...e,objects:e.objects.map(e=>e.id===t.id?(({pinned:e,...t})=>t)(e):e)};case`place`:return{...e,objects:e.objects.map(e=>e.id===t.id?{...e,placement:t.placement}:e)};case`presence`:return{...e,presence:{...e.presence,state:t.state??e.presence.state,style:t.style??e.presence.style}};case`mood`:return{...e,mood:{accent:t.accent??e.mood.accent,intensity:t.intensity??e.mood.intensity}}}}function zT(e,t){let n=t;if(n&&typeof n==`object`){if(n.type===`conn`)return{...e,connection:n.value};if(n.type===`chat.seed`){let t=Array.isArray(n.lines)?n.lines:[];return e.chat.length===0?{...e,chat:FT(t)}:{...e,chat:FT([...t,...e.chat])}}if(n.type===`alert.add`)return{...e,alerts:[...e.alerts.slice(-3),{id:++IT,level:n.level,text:n.text}]};if(n.type===`camera.enable`)return{...e,camera:{enabled:n.value,stream:n.value?e.camera.stream:null}};if(n.type===`camera.open`)return{...e,camera:{...e.camera,stream:n.stream}};if(n.type===`camera.closed`)return{...e,camera:{...e.camera,stream:null}};if(n.type===`challenge.dismiss`)return e.challenge?.id===n.id?{...e,challenge:null}:e;if(n.type===`voice.mode`)return{...e,voice:{...e.voice,mode:n.mode,level:n.mode===`idle`?0:e.voice.level}};if(n.type===`voice.level`){let t=Number.isFinite(n.level)?Math.min(1,Math.max(0,n.level)):0;return{...e,voice:{...e.voice,level:t}}}if(n.type===`object.dismiss`)return{...e,objects:e.objects.filter(e=>e.id!==n.id)};if(n.type===`object.place`)return{...e,objects:e.objects.map(e=>e.id===n.id?{...e,placement:n.placement}:e)};if(n.type===`alert.dismiss`)return{...e,alerts:e.alerts.filter(e=>e.id!==n.id)}}let r=Yl.safeParse(t);if(!r.success)return e;let i=r.data;switch(i.type){case`snapshot`:return{...e,scene:i.stage.scene,objects:i.stage.objects,presence:{...e.presence,state:i.stage.presence.state,style:i.stage.presence.style},mood:i.stage.mood,approval:i.pendingApproval??null};case`stage`:return RT(e,i.command);case`chat.user`:return{...e,chat:FT([...e.chat,{role:`user`,text:i.text}]),chatLive:!1};case`ui.open`:return{...e,uiOpen:{n:(e.uiOpen?.n??0)+1,...i.integration?{integration:i.integration}:{}}};case`ui`:return{...e,view:i.view,look:i.look??e.look,ownerName:i.ownerName??e.ownerName,assistantName:i.assistantName??e.assistantName,hud:i.hud??e.hud,music:i.music??e.music,viewKnown:!0};case`music.command`:{let{type:t,...n}=i;return{...e,musicCmd:{n:(e.musicCmd?.n??0)+1,command:n}}}case`caption.delta`:{let t=e.captionDone,n=e.chat.at(-1),r=e.chatLive&&n?.role===`assistant`?[...e.chat.slice(0,-1),{role:`assistant`,text:n.text+i.text}]:FT([...e.chat,{role:`assistant`,text:i.text}]);return{...e,chat:r,chatLive:!0,captions:(t?``:e.captions)+i.text,captionDone:!1,presence:{...e.presence,amplitude:LT(.3+i.text.length*.04),pulse:e.presence.pulse+1}}}case`caption.end`:return{...e,chatLive:!1,captionDone:!0,presence:{...e.presence,amplitude:0}};case`approval.request`:{let{type:t,...n}=i;return{...e,approval:n}}case`approval.resolved`:return e.approval?.id===i.id?{...e,approval:null}:e;case`alert`:return{...e,alerts:[...e.alerts.slice(-3),{id:++IT,level:i.level,text:i.text}]};case`activity`:return{...e,activity:i.text};case`status`:return{...e,busy:i.busy,activity:i.busy?e.activity:null,deviceOnline:i.deviceOnline,voice:{...e.voice,available:i.voiceAvailable??e.voice.available,enrolled:i.voiceEnrolled??e.voice.enrolled}};case`error`:return{...e,alerts:[...e.alerts.slice(-3),{id:++IT,level:`error`,text:i.message}]};case`voice.heard`:return{...e,captions:i.trust===`guest`?`Guest: ${i.text}`:i.trust===`member`&&i.speaker?`${i.speaker}: ${i.text}`:i.text,captionDone:!0,speaker:{name:i.trust===`member`?i.speaker??null:null,trust:i.trust??`unverified`,seq:(e.speaker?.seq??0)+1}};case`voice.challenge`:return{...e,challenge:{id:i.id,text:i.text}};case`voice.challenge.end`:return e.challenge?.id===i.id?{...e,challenge:null}:e;case`audio.chunk`:case`audio.stop`:return e;case`camera.request`:case`camera.cancel`:case`screen.request`:case`screen.cancel`:return e}}var BT=1024,VT=.8,HT=300;function UT(e,t){let n=Math.min(1,BT/Math.max(e,t));return{width:Math.round(e*n),height:Math.round(t*n)}}function WT(e){let t=e?.name;return t===`NotAllowedError`||t===`SecurityError`?`permission`:t===`NotFoundError`||t===`OverconstrainedError`?`no-camera`:`busy`}async function GT(){if(!navigator.mediaDevices?.getUserMedia)throw Object.assign(Error(`This browser cannot use the camera here (use localhost or HTTPS).`),{name:`NotFoundError`});return navigator.mediaDevices.getUserMedia({video:{width:{ideal:1280}},audio:!1})}async function KT(e,t=HT){let n=document.createElement(`video`);n.muted=!0,n.playsInline=!0,n.srcObject=e,await n.play(),await new Promise(e=>setTimeout(e,t));let{width:r,height:i}=UT(n.videoWidth||640,n.videoHeight||480),a=document.createElement(`canvas`);return a.width=r,a.height=i,a.getContext(`2d`).drawImage(n,0,0,r,i),n.srcObject=null,new Promise((e,t)=>a.toBlob(n=>n?e(n):t(Error(`Could not encode the picture.`)),`image/jpeg`,VT))}var qT=class{opts;active=null;constructor(e){this.opts=e}async handle(e){if(e.type===`camera.cancel`){let t=this.active;t&&t.id===e.id&&(t.cancelled=!0,this.release(t));return}if(!this.opts.enabled())return this.opts.send({type:`camera.denied`,id:e.id,reason:`off`});if(this.active)return this.opts.send({type:`camera.denied`,id:e.id,reason:`busy`});let t={id:e.id,cancelled:!1,stream:null,opened:!1,released:!1};this.active=t;try{let n=await(this.opts.open??GT)();if(t.stream=n,t.cancelled){n.getTracks().forEach(e=>e.stop());return}t.opened=!0,this.opts.dispatch({type:`camera.open`,stream:n});let r=await(this.opts.frame??(e=>KT(e)))(n);if(t.cancelled)return;this.release(t);try{await this.opts.upload(e.id,r)}catch{this.opts.dispatch({type:`alert.add`,level:`warn`,text:`Could not send the camera picture to Friend.`})}}catch(n){t.cancelled||this.opts.send({type:`camera.denied`,id:e.id,reason:WT(n)})}finally{this.release(t),this.active===t&&(this.active=null)}}dispose(){let e=this.active;e&&(e.cancelled=!0,this.release(e))}release(e){e.released||(e.released=!0,e.stream?.getTracks().forEach(e=>e.stop()),e.opened&&this.opts.dispatch({type:`camera.closed`}))}};function JT(e,t){if(e.match(/^[a-z]+:\/\//i))return e;if(e.match(/^\/\//))return window.location.protocol+e;if(e.match(/^[a-z]+:/i))return e;let n=document.implementation.createHTMLDocument(),r=n.createElement(`base`),i=n.createElement(`a`);return n.head.appendChild(r),n.body.appendChild(i),t&&(r.href=t),i.href=e,i.href}var YT=(()=>{let e=0,t=()=>`0000${(Math.random()*36**4<<0).toString(36)}`.slice(-4);return()=>(e+=1,`u${t()}${e}`)})();function XT(e){let t=[];for(let n=0,r=e.length;n<r;n++)t.push(e[n]);return t}var ZT=null;function QT(e={}){return ZT||(e.includeStyleProperties?(ZT=e.includeStyleProperties,ZT):(ZT=XT(window.getComputedStyle(document.documentElement)),ZT))}function $T(e,t){let n=(e.ownerDocument.defaultView||window).getComputedStyle(e).getPropertyValue(t);return n?parseFloat(n.replace(`px`,``)):0}function eE(e){let t=$T(e,`border-left-width`),n=$T(e,`border-right-width`);return e.clientWidth+t+n}function tE(e){let t=$T(e,`border-top-width`),n=$T(e,`border-bottom-width`);return e.clientHeight+t+n}function nE(e,t={}){return{width:t.width||eE(e),height:t.height||tE(e)}}function rE(){let e,t;try{t=process}catch{}let n=t&&t.env?t.env.devicePixelRatio:null;return n&&(e=parseInt(n,10),Number.isNaN(e)&&(e=1)),e||window.devicePixelRatio||1}var iE=16384;function aE(e){(e.width>iE||e.height>iE)&&(e.width>iE&&e.height>iE?e.width>e.height?(e.height*=iE/e.width,e.width=iE):(e.width*=iE/e.height,e.height=iE):e.width>iE?(e.height*=iE/e.width,e.width=iE):(e.width*=iE/e.height,e.height=iE))}function oE(e){return new Promise((t,n)=>{let r=new Image;r.onload=()=>{r.decode().then(()=>{requestAnimationFrame(()=>t(r))})},r.onerror=n,r.crossOrigin=`anonymous`,r.decoding=`async`,r.src=e})}async function sE(e){return Promise.resolve().then(()=>new XMLSerializer().serializeToString(e)).then(encodeURIComponent).then(e=>`data:image/svg+xml;charset=utf-8,${e}`)}async function cE(e,t,n){let r=`http://www.w3.org/2000/svg`,i=document.createElementNS(r,`svg`),a=document.createElementNS(r,`foreignObject`);return i.setAttribute(`width`,`${t}`),i.setAttribute(`height`,`${n}`),i.setAttribute(`viewBox`,`0 0 ${t} ${n}`),a.setAttribute(`width`,`100%`),a.setAttribute(`height`,`100%`),a.setAttribute(`x`,`0`),a.setAttribute(`y`,`0`),a.setAttribute(`externalResourcesRequired`,`true`),i.appendChild(a),a.appendChild(e),sE(i)}var lE=(e,t)=>{if(e instanceof t)return!0;let n=Object.getPrototypeOf(e);return n===null?!1:n.constructor.name===t.name||lE(n,t)};function uE(e){let t=e.getPropertyValue(`content`);return`${e.cssText} content: '${t.replace(/'|"/g,``)}';`}function dE(e,t){return QT(t).map(t=>`${t}: ${e.getPropertyValue(t)}${e.getPropertyPriority(t)?` !important`:``};`).join(` `)}function fE(e,t,n,r){let i=`.${e}:${t}`,a=n.cssText?uE(n):dE(n,r);return document.createTextNode(`${i}{${a}}`)}function pE(e,t,n,r){let i=window.getComputedStyle(e,n),a=i.getPropertyValue(`content`);if(a===``||a===`none`)return;let o=YT();try{t.className=`${t.className} ${o}`}catch{return}let s=document.createElement(`style`);s.appendChild(fE(o,n,i,r)),t.appendChild(s)}function mE(e,t,n){pE(e,t,`:before`,n),pE(e,t,`:after`,n)}var hE=`application/font-woff`,gE=`image/jpeg`,_E={woff:hE,woff2:hE,ttf:`application/font-truetype`,eot:`application/vnd.ms-fontobject`,png:`image/png`,jpg:gE,jpeg:gE,gif:`image/gif`,tiff:`image/tiff`,svg:`image/svg+xml`,webp:`image/webp`};function vE(e){let t=/\.([^./]*?)$/g.exec(e);return t?t[1]:``}function yE(e){return _E[vE(e).toLowerCase()]||``}function bE(e){return e.split(/,/)[1]}function xE(e){return e.search(/^(data:)/)!==-1}function SE(e,t){return`data:${t};base64,${e}`}async function CE(e,t,n){let r=await fetch(e,t);if(r.status===404)throw Error(`Resource "${r.url}" not found`);let i=await r.blob();return new Promise((e,t)=>{let a=new FileReader;a.onerror=t,a.onloadend=()=>{try{e(n({res:r,result:a.result}))}catch(e){t(e)}},a.readAsDataURL(i)})}var wE={};function TE(e,t,n){let r=e.replace(/\?.*/,``);return n&&(r=e),/ttf|otf|eot|woff2?/i.test(r)&&(r=r.replace(/.*\//,``)),t?`[${t}]${r}`:r}async function EE(e,t,n){let r=TE(e,t,n.includeQueryParams);if(wE[r]!=null)return wE[r];n.cacheBust&&(e+=(/\?/.test(e)?`&`:`?`)+new Date().getTime());let i;try{i=SE(await CE(e,n.fetchRequestInit,({res:e,result:n})=>(t||=e.headers.get(`Content-Type`)||``,bE(n))),t)}catch(t){i=n.imagePlaceholder||``;let r=`Failed to fetch resource: ${e}`;t&&(r=typeof t==`string`?t:t.message),r&&console.warn(r)}return wE[r]=i,i}async function DE(e){let t=e.toDataURL();return t===`data:,`?e.cloneNode(!1):oE(t)}async function OE(e,t){if(e.currentSrc){let t=document.createElement(`canvas`),n=t.getContext(`2d`);return t.width=e.clientWidth,t.height=e.clientHeight,n?.drawImage(e,0,0,t.width,t.height),oE(t.toDataURL())}let n=e.poster;return oE(await EE(n,yE(n),t))}async function kE(e,t){try{if(e?.contentDocument?.body)return await zE(e.contentDocument.body,t,!0)}catch{}return e.cloneNode(!1)}async function AE(e,t){return lE(e,HTMLCanvasElement)?DE(e):lE(e,HTMLVideoElement)?OE(e,t):lE(e,HTMLIFrameElement)?kE(e,t):e.cloneNode(ME(e))}var jE=e=>e.tagName!=null&&e.tagName.toUpperCase()===`SLOT`,ME=e=>e.tagName!=null&&e.tagName.toUpperCase()===`SVG`;async function NE(e,t,n){if(ME(t))return t;let r=[];return r=jE(e)&&e.assignedNodes?XT(e.assignedNodes()):lE(e,HTMLIFrameElement)&&e.contentDocument?.body?XT(e.contentDocument.body.childNodes):XT((e.shadowRoot??e).childNodes),r.length===0||lE(e,HTMLVideoElement)||await r.reduce((e,r)=>e.then(()=>zE(r,n)).then(e=>{e&&t.appendChild(e)}),Promise.resolve()),t}function PE(e,t,n){let r=t.style;if(!r)return;let i=window.getComputedStyle(e);i.cssText?(r.cssText=i.cssText,r.transformOrigin=i.transformOrigin):QT(n).forEach(n=>{let a=i.getPropertyValue(n);n===`font-size`&&a.endsWith(`px`)&&(a=`${Math.floor(parseFloat(a.substring(0,a.length-2)))-.1}px`),lE(e,HTMLIFrameElement)&&n===`display`&&a===`inline`&&(a=`block`),n===`d`&&t.getAttribute(`d`)&&(a=`path(${t.getAttribute(`d`)})`),r.setProperty(n,a,i.getPropertyPriority(n))})}function FE(e,t){lE(e,HTMLTextAreaElement)&&(t.innerHTML=e.value),lE(e,HTMLInputElement)&&t.setAttribute(`value`,e.value)}function IE(e,t){if(lE(e,HTMLSelectElement)){let n=t,r=Array.from(n.children).find(t=>e.value===t.getAttribute(`value`));r&&r.setAttribute(`selected`,``)}}function LE(e,t,n){return lE(t,Element)&&(PE(e,t,n),mE(e,t,n),FE(e,t),IE(e,t)),t}async function RE(e,t){let n=e.querySelectorAll?e.querySelectorAll(`use`):[];if(n.length===0)return e;let r={};for(let i=0;i<n.length;i++){let a=n[i].getAttribute(`xlink:href`);if(a){let n=e.querySelector(a),i=document.querySelector(a);!n&&i&&!r[a]&&(r[a]=await zE(i,t,!0))}}let i=Object.values(r);if(i.length){let t=`http://www.w3.org/1999/xhtml`,n=document.createElementNS(t,`svg`);n.setAttribute(`xmlns`,t),n.style.position=`absolute`,n.style.width=`0`,n.style.height=`0`,n.style.overflow=`hidden`,n.style.display=`none`;let r=document.createElementNS(t,`defs`);n.appendChild(r);for(let e=0;e<i.length;e++)r.appendChild(i[e]);e.appendChild(n)}return e}async function zE(e,t,n){return!n&&t.filter&&!t.filter(e)?null:Promise.resolve(e).then(e=>AE(e,t)).then(n=>NE(e,n,t)).then(n=>LE(e,n,t)).then(e=>RE(e,t))}var BE=/url\((['"]?)([^'"]+?)\1\)/g,VE=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,HE=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;function UE(e){let t=e.replace(/([.*+?^${}()|\[\]\/\\])/g,`\\$1`);return RegExp(`(url\\(['"]?)(${t})(['"]?\\))`,`g`)}function WE(e){let t=[];return e.replace(BE,(e,n,r)=>(t.push(r),e)),t.filter(e=>!xE(e))}async function GE(e,t,n,r,i){try{let a=n?JT(t,n):t,o=yE(t),s;return s=i?SE(await i(a),o):await EE(a,o,r),e.replace(UE(t),`$1${s}$3`)}catch{}return e}function KE(e,{preferredFontFormat:t}){return t?e.replace(HE,e=>{for(;;){let[n,,r]=VE.exec(e)||[];if(!r)return``;if(r===t)return`src: ${n};`}}):e}function qE(e){return e.search(BE)!==-1}async function JE(e,t,n){if(!qE(e))return e;let r=KE(e,n);return WE(r).reduce((e,r)=>e.then(e=>GE(e,r,t,n)),Promise.resolve(r))}async function YE(e,t,n){let r=t.style?.getPropertyValue(e);if(r){let i=await JE(r,null,n);return t.style.setProperty(e,i,t.style.getPropertyPriority(e)),!0}return!1}async function XE(e,t){await YE(`background`,e,t)||await YE(`background-image`,e,t),await YE(`mask`,e,t)||await YE(`-webkit-mask`,e,t)||await YE(`mask-image`,e,t)||await YE(`-webkit-mask-image`,e,t)}async function ZE(e,t){let n=lE(e,HTMLImageElement);if((!n||xE(e.src))&&(!lE(e,SVGImageElement)||xE(e.href.baseVal)))return;let r=n?e.src:e.href.baseVal,i=await EE(r,yE(r),t);await new Promise((r,a)=>{e.onload=r,e.onerror=t.onImageErrorHandler?(...e)=>{try{r(t.onImageErrorHandler(...e))}catch(e){a(e)}}:a;let o=e;o.decode&&=r,o.loading===`lazy`&&(o.loading=`eager`),n?(e.srcset=``,e.src=i):e.href.baseVal=i})}async function QE(e,t){let n=XT(e.childNodes).map(e=>$E(e,t));await Promise.all(n).then(()=>e)}async function $E(e,t){lE(e,Element)&&(await XE(e,t),await ZE(e,t),await QE(e,t))}function eD(e,t){let{style:n}=e;t.backgroundColor&&(n.backgroundColor=t.backgroundColor),t.width&&(n.width=`${t.width}px`),t.height&&(n.height=`${t.height}px`);let r=t.style;return r!=null&&Object.keys(r).forEach(e=>{n[e]=r[e]}),e}var tD={};async function nD(e){let t=tD[e];return t??(t={url:e,cssText:await(await fetch(e)).text()},tD[e]=t,t)}async function rD(e,t){let n=e.cssText,r=/url\(["']?([^"')]+)["']?\)/g,i=(n.match(/url\([^)]+\)/g)||[]).map(async i=>{let a=i.replace(r,`$1`);return a.startsWith(`https://`)||(a=new URL(a,e.url).href),CE(a,t.fetchRequestInit,({result:e})=>(n=n.replace(i,`url(${e})`),[i,e]))});return Promise.all(i).then(()=>n)}function iD(e){if(e==null)return[];let t=[],n=e.replace(/(\/\*[\s\S]*?\*\/)/gi,``),r=RegExp(`((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})`,`gi`);for(;;){let e=r.exec(n);if(e===null)break;t.push(e[0])}n=n.replace(r,``);let i=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,a=RegExp(`((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})`,`gi`);for(;;){let e=i.exec(n);if(e===null){if(e=a.exec(n),e===null)break;i.lastIndex=a.lastIndex}else a.lastIndex=i.lastIndex;t.push(e[0])}return t}async function aD(e,t){let n=[],r=[];return e.forEach(n=>{if(`cssRules`in n)try{XT(n.cssRules||[]).forEach((e,i)=>{if(e.type===CSSRule.IMPORT_RULE){let a=i+1,o=e.href,s=nD(o).then(e=>rD(e,t)).then(e=>iD(e).forEach(e=>{try{n.insertRule(e,e.startsWith(`@import`)?a+=1:n.cssRules.length)}catch(t){console.error(`Error inserting rule from remote css`,{rule:e,error:t})}})).catch(e=>{console.error(`Error loading remote css`,e.toString())});r.push(s)}})}catch(i){let a=e.find(e=>e.href==null)||document.styleSheets[0];n.href!=null&&r.push(nD(n.href).then(e=>rD(e,t)).then(e=>iD(e).forEach(e=>{a.insertRule(e,a.cssRules.length)})).catch(e=>{console.error(`Error loading remote stylesheet`,e)})),console.error(`Error inlining remote css file`,i)}}),Promise.all(r).then(()=>(e.forEach(e=>{if(`cssRules`in e)try{XT(e.cssRules||[]).forEach(e=>{n.push(e)})}catch(t){console.error(`Error while reading CSS rules from ${e.href}`,t)}}),n))}function oD(e){return e.filter(e=>e.type===CSSRule.FONT_FACE_RULE).filter(e=>qE(e.style.getPropertyValue(`src`)))}async function sD(e,t){if(e.ownerDocument==null)throw Error(`Provided element is not within a Document`);return oD(await aD(XT(e.ownerDocument.styleSheets),t))}function cD(e){return e.trim().replace(/["']/g,``)}function lD(e){let t=new Set;function n(e){(e.style.fontFamily||getComputedStyle(e).fontFamily).split(`,`).forEach(e=>{t.add(cD(e))}),Array.from(e.children).forEach(e=>{e instanceof HTMLElement&&n(e)})}return n(e),t}async function uD(e,t){let n=await sD(e,t),r=lD(e);return(await Promise.all(n.filter(e=>r.has(cD(e.style.fontFamily))).map(e=>{let n=e.parentStyleSheet?e.parentStyleSheet.href:null;return JE(e.cssText,n,t)}))).join(`
|
|
4456
|
-
`)}async function dD(e,t){let n=t.fontEmbedCSS==null?t.skipFonts?null:await uD(e,t):t.fontEmbedCSS;if(n){let t=document.createElement(`style`),r=document.createTextNode(n);t.appendChild(r),e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}}async function fD(e,t={}){let{width:n,height:r}=nE(e,t),i=await zE(e,t,!0);return await dD(i,t),await $E(i,t),eD(i,t),await cE(i,n,r)}async function pD(e,t={}){let{width:n,height:r}=nE(e,t),i=await oE(await fD(e,t)),a=document.createElement(`canvas`),o=a.getContext(`2d`),s=t.pixelRatio||rE(),c=t.canvasWidth||n,l=t.canvasHeight||r;return a.width=c*s,a.height=l*s,t.skipAutoScale||aE(a),a.style.width=`${c}`,a.style.height=`${l}`,t.backgroundColor&&(o.fillStyle=t.backgroundColor,o.fillRect(0,0,a.width,a.height)),o.drawImage(i,0,0,a.width,a.height),a}var mD=1600,hD=.85;function gD(e,t){let n=Math.min(1,mD/Math.max(e,t,1));return{width:Math.max(1,Math.round(e*n)),height:Math.max(1,Math.round(t*n))}}async function _D(){let e=document.documentElement.getBoundingClientRect(),t=await pD(document.body,{width:Math.round(e.width),height:Math.round(e.height),pixelRatio:1,backgroundColor:`#050b10`,filter:e=>!(e instanceof HTMLElement&&e.dataset.noCapture!==void 0)}),n=gD(t.width,t.height),r=document.createElement(`canvas`);return r.width=n.width,r.height=n.height,r.getContext(`2d`).drawImage(t,0,0,n.width,n.height),new Promise((e,t)=>r.toBlob(n=>n?e(n):t(Error(`Could not encode the picture.`)),`image/jpeg`,hD))}var vD=class{opts;active=null;constructor(e){this.opts=e}async handle(e){if(e.type===`screen.cancel`){this.active&&this.active.id===e.id&&(this.active.cancelled=!0);return}if(this.active)return this.opts.send({type:`screen.denied`,id:e.id,reason:`busy`});let t={id:e.id,cancelled:!1};this.active=t;try{let n=await(this.opts.capture??_D)();if(t.cancelled)return;try{await this.opts.upload(e.id,n)}catch{this.opts.dispatch({type:`alert.add`,level:`warn`,text:`Could not send the picture of the screen to Friend.`})}}catch(n){t.cancelled||this.opts.send({type:`screen.denied`,id:e.id,reason:yD(n)})}finally{this.active===t&&(this.active=null)}}dispose(){this.active&&(this.active.cancelled=!0)}};function yD(e){return e?.name===`NotSupportedError`?`unsupported`:`failed`}var bD={401:`Please sign in again.`,413:`That recording was too long.`,409:`Friend is busy with the last request. Try again in a moment.`,429:`You're talking too fast. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function xD(e,t){let n;try{n=await fetch(`/api/voice/utterance`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e,signal:t})}catch(e){throw e.name===`AbortError`?e:Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||bD[n.status]||`The voice request failed (${n.status}).`)}let r=await n.json();return{text:typeof r.text==`string`?r.text:``}}var SD=0,CD=new Set;function wD(e){return CD.add(e),()=>CD.delete(e)}var TD=e=>CD.forEach(t=>{try{t(e)}catch{}}),ED=e=>/not compatible|audio capture|audiosession/i.test(String(e?.message??e));function DD(e){try{let t=navigator.audioSession;t&&t.type!==e&&(t.type=e)}catch{}}function OD(){SD===0&&DD(`playback`)}function kD(){SD++,SD===1&&TD(!0),DD(`play-and-record`);let e=!1;return()=>{e||(e=!0,SD=Math.max(0,SD-1),SD===0&&(DD(`playback`),TD(!1)))}}var AD=4096,jD=8,MD=20,ND=6e6;function PD(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}catch{return null}}var FD=class{ctx=null;analyser=null;pending=new Map;queue=[];current=null;busy=!1;gen=0;isPlaying=!1;unwatch=null;listeners=new Set;unlock(){OD();let e=this.ensureContext();e.state!==`running`&&e.resume().catch(()=>{})}locked(){return!this.ctx||this.ctx.state!==`running`}enqueue(e){if(!Number.isInteger(e.seq)||e.seq<0||e.seq>AD)return;let t=PD(e.data);if(!t)return;let n=this.pending.get(e.id);if(n||(this.pending.size>=jD&&this.pending.delete(this.pending.keys().next().value),n={parts:new Map,lastSeq:null,bytes:0},this.pending.set(e.id,n)),n.bytes+=t.length,n.bytes>ND){this.pending.delete(e.id);return}if(n.parts.set(e.seq,t),e.last&&(n.lastSeq=e.seq),n.lastSeq===null||n.parts.size!==n.lastSeq+1)return;this.pending.delete(e.id);let r=new Uint8Array([...n.parts.values()].reduce((e,t)=>e+t.length,0)),i=0;for(let e=0;e<=n.lastSeq;e++){let t=n.parts.get(e);if(!t)return;r.set(t,i),i+=t.length}for(this.queue.push(r.buffer);this.queue.length>MD;)this.queue.shift();this.pump()}stop(){this.gen++,this.queue=[],this.pending.clear(),this.busy=!1;let e=this.current;if(this.current=null,e){e.onended=null;try{e.stop()}catch{}}this.setPlaying(!1)}dispose(){this.stop(),this.ctx?.close().catch(()=>{}),this.unwatch?.(),this.unwatch=null,this.ctx=null,this.analyser=null}playing(){return this.isPlaying}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}level(){if(!this.analyser||!this.isPlaying)return 0;let e=new Uint8Array(this.analyser.fftSize);this.analyser.getByteTimeDomainData(e);let t=0;for(let n of e)t+=((n-128)/128)**2;return Math.min(1,Math.sqrt(t/e.length)*4)}ensureContext(){if(!this.ctx){let e=window.AudioContext??window.webkitAudioContext;this.ctx=new e,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=1024,this.analyser.connect(this.ctx.destination);let t=this.ctx;this.unwatch?.(),this.unwatch=wD(e=>{e&&t.state===`running`?t.suspend().catch(()=>{}):!e&&t.state!==`running`&&t.state!==`closed`&&t.resume().catch(()=>{})})}return this.ctx}setPlaying(e){this.isPlaying!==e&&(this.isPlaying=e,this.listeners.forEach(t=>t(e)))}async pump(){if(this.busy)return;let e=this.queue.shift();if(!e){this.setPlaying(!1);return}this.busy=!0;let t=this.gen;try{let n=this.ensureContext();if(n.state!==`running`){try{await n.resume()}catch{}if(t!==this.gen)return;if(n.state!==`running`){this.queue.unshift(e),this.busy=!1;return}}let r=await n.decodeAudioData(e);if(t!==this.gen)return;let i=n.createBufferSource();i.buffer=r,i.connect(this.analyser),i.onended=()=>{this.current===i&&(this.current=null,this.busy=!1,this.pump())},this.current=i,this.setPlaying(!0),i.start()}catch{if(t!==this.gen)return;this.busy=!1,this.pump()}}},ID=e=>new Promise(t=>setTimeout(t,e)),LD=[`audio/webm;codecs=opus`,`audio/webm`,`audio/mp4`,`audio/ogg;codecs=opus`],RD=3e3;function zD(e){let t=e;return t?.name===`NotAllowedError`||t?.name===`SecurityError`?Error(`Microphone permission was denied. Allow it in the browser to talk.`):t?.name===`NotFoundError`||t?.name===`OverconstrainedError`?Error(`No microphone was found.`):Error(t?.message||`Could not open the microphone.`)}var BD=class e{opts;stream=null;rec=null;chunks=[];ctx=null;analyser=null;timer=null;starting=!1;leaveSession=null;constructor(e={}){this.opts=e}static supported(){return typeof navigator<`u`&&!!navigator.mediaDevices?.getUserMedia&&typeof MediaRecorder<`u`}get active(){return this.rec!==null}async start(){if(!(this.rec||this.starting)){if(!e.supported())throw Error(`This browser cannot record audio here (use localhost or HTTPS).`);this.starting=!0;try{this.leaveSession=kD();try{let e=()=>navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0}});try{this.stream=await e()}catch(t){if(!ED(t))throw t;await ID(250),this.leaveSession?.(),this.leaveSession=kD(),this.stream=await e()}}catch(e){throw this.leaveSession?.(),this.leaveSession=null,zD(e)}try{let e=LD.find(e=>MediaRecorder.isTypeSupported(e));this.chunks=[];let t=new MediaRecorder(this.stream,e?{mimeType:e}:void 0);t.ondataavailable=e=>{e.data&&e.data.size>0&&this.chunks.push(e.data)},t.onerror=()=>this.failed();for(let e of this.stream.getTracks())e.onended=()=>this.failed();this.openMeter(this.stream),t.start(250),this.rec=t,this.opts.maxMs&&(this.timer=setTimeout(()=>{this.timer=null,this.opts.onLimit?.()},this.opts.maxMs))}catch(e){throw this.release(),zD(e)}}finally{this.starting=!1}}}stop(){let e=this.rec;return e?new Promise(t=>{let n=!1,r=null,i=()=>{if(n)return;n=!0,r&&clearTimeout(r);let i=new Blob(this.chunks,{type:e.mimeType||`audio/webm`});this.release(),t(i)};if(r=setTimeout(i,RD),e.onstop=i,e.state===`inactive`)return i();try{e.stop()}catch{i()}}):Promise.reject(Error(`Not recording.`))}cancel(){let e=this.rec;if(e){e.ondataavailable=null,e.onstop=null,e.onerror=null;try{e.state!==`inactive`&&e.stop()}catch{}}this.release()}level(){if(!this.analyser||!this.rec)return 0;let e=new Uint8Array(this.analyser.fftSize);this.analyser.getByteTimeDomainData(e);let t=0;for(let n of e)t+=((n-128)/128)**2;return Math.min(1,Math.sqrt(t/e.length)*4)}failed(){this.rec&&(this.cancel(),this.opts.onError?.())}openMeter(e){try{this.ctx=new AudioContext,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=1024,this.ctx.createMediaStreamSource(e).connect(this.analyser)}catch{this.analyser=null}}release(){this.timer&&clearTimeout(this.timer),this.timer=null,this.stream?.getTracks().forEach(e=>{e.onended=null,e.stop()}),this.ctx?.close().catch(()=>{}),this.stream=null,this.rec=null,this.ctx=null,this.analyser=null,this.chunks=[],this.leaveSession?.(),this.leaveSession=null}},VD=2e3,HD=()=>typeof window<`u`&&window.isSecureContext===!1,UD=50,WD=class{deps;recorder;player;mode=`idle`;pressed=!1;disposed=!1;uploads=0;toldAboutSound=!1;abort=null;poll=null;unsubscribe;constructor(e){this.deps=e;let t=()=>this.recorderFailed();this.recorder=e.recorder??e.makeRecorder?.(t)??new BD({maxMs:6e4,onLimit:()=>void this.pressEnd(),onError:t}),this.player=e.player??new FD,this.unsubscribe=this.player.onChange(e=>{this.mode!==`listening`&&this.mode!==`transcribing`&&this.setMode(e?`speaking`:`idle`)})}async pressStart(){if(!(this.pressed||this.disposed)){if(!this.deps.available()){this.alert(`warn`,`Voice is not available. Run: friend voice setup`);return}if(!(this.deps.supported?.()??BD.supported())){this.alert(`warn`,HD()?`This page is not secure, so the browser blocks the microphone. On the PC run: friend lan https on, restart Friend, and open the https:// address.`:`This browser cannot record audio here (use localhost or HTTPS).`);return}this.pressed=!0,this.player.unlock(),this.player.playing()&&(this.deps.send({type:`voice.interrupt`}),this.player.stop());try{await this.recorder.start()}catch(e){this.pressed=!1,this.alert(`error`,e.message),this.setMode(`idle`);return}if(!this.pressed){this.recorder.cancel(),this.setMode(`idle`);return}this.setMode(`listening`)}}async pressEnd(){if(!this.pressed||(this.pressed=!1,!this.recorder.active))return;let e=await this.recorder.stop();if(e.size<VD){this.alert(`info`,`Hold the key a little longer while you speak.`),this.setMode(`idle`);return}this.setMode(`transcribing`);let t=new AbortController;this.abort=t,this.uploads++;try{let{text:n}=await this.deps.post(e,t.signal);n.trim()||this.alert(`info`,`I didn't catch that.`)}catch(e){e.name!==`AbortError`&&this.alert(`error`,e.message)}finally{this.uploads--,this.abort===t&&(this.abort=null),this.settle()}}blur(){this.pressed&&(this.pressed=!1,this.recorder.cancel(),this.setMode(`idle`))}handleServer(e){if(e.type!==`audio.chunk`)return this.player.stop();this.player.enqueue(e),!this.toldAboutSound&&this.player.locked?.()&&(this.toldAboutSound=!0,this.deps.dispatch({type:`alert.add`,level:`info`,text:`Sound is blocked by the browser. Click or press a key once anywhere on the page to hear me.`}))}unlock(){this.player.unlock()}dispose(){this.disposed=!0,this.pressed=!1,this.stopPolling(),this.abort?.abort(),this.recorder.cancel(),this.player.stop(),this.player.dispose?.(),this.unsubscribe()}recorderFailed(){this.pressed=!1,this.recorder.cancel(),this.alert(`error`,`The microphone stopped working.`),this.setMode(`idle`)}settle(){this.uploads>0||this.mode!==`transcribing`||this.setMode(this.player.playing()?`speaking`:`idle`)}setMode(e){this.disposed||(this.mode=e,this.deps.dispatch({type:`voice.mode`,mode:e}),e===`listening`||e===`speaking`?this.startPolling():this.stopPolling())}startPolling(){this.stopPolling(),this.poll=setInterval(()=>{let e=this.mode===`listening`?this.recorder.level():this.player.level();this.deps.dispatch({type:`voice.level`,level:e})},UD)}stopPolling(){this.poll&&clearInterval(this.poll),this.poll=null}alert(e,t){this.disposed||this.deps.dispatch({type:`alert.add`,level:e,text:t})}};function GD(e){let[t,n]=(0,l.useReducer)(zT,NT),r=(0,l.useRef)(null),i=(0,l.useRef)(null),a=(0,l.useRef)(null),o=(0,l.useRef)(e);o.current=e;let s=(0,l.useRef)(t);return s.current=t,(0,l.useEffect)(()=>{let e=MT();r.current=e;let t=new WD({send:t=>e.send(t),dispatch:e=>n(e),post:xD,available:()=>s.current.voice.available});i.current=t;let c=new qT({send:t=>e.send(t),dispatch:e=>n(e),enabled:()=>s.current.camera.enabled,upload:async(e,t)=>{let n=await fetch(`/api/camera/frame/${encodeURIComponent(e)}`,{method:`POST`,headers:{"content-type":`image/jpeg`},body:t});if(!n.ok)throw Error(`upload failed (${n.status})`)}});a.current=c;let l=new vD({send:t=>e.send(t),dispatch:e=>n(e),upload:async(e,t)=>{let n=await fetch(`/api/screen/frame/${encodeURIComponent(e)}`,{method:`POST`,headers:{"content-type":`image/jpeg`},body:t});if(!n.ok)throw Error(`upload failed (${n.status})`)}}),u=e.onMessage(e=>{n(e);let r=e?.type,i=e?.id;(r===`camera.request`||r===`camera.cancel`)&&typeof i==`string`&&c.handle({type:r,id:i}),(r===`screen.request`||r===`screen.cancel`)&&typeof i==`string`&&l.handle({type:r,id:i}),(r===`audio.chunk`||r===`audio.stop`)&&t.handleServer(e)}),d=e.onState(e=>{n({type:`conn`,value:e}),e===`unauthorized`&&o.current(),e===`elsewhere`&&(t.blur(),c.dispose(),l.dispose())});return()=>{u(),d(),t.dispose(),c.dispose(),l.dispose(),e.close(),i.current=null,a.current=null,r.current=null}},[]),(0,l.useEffect)(()=>{t.camera.enabled||a.current?.dispose()},[t.camera.enabled]),{state:t,send:(0,l.useCallback)(e=>r.current?.send(e),[]),dispatch:(0,l.useCallback)(e=>n(e),[]),voice:(0,l.useMemo)(()=>({pressStart:()=>void i.current?.pressStart(),pressEnd:()=>void i.current?.pressEnd(),blur:()=>i.current?.blur(),unlock:()=>i.current?.unlock()}),[]),useHere:(0,l.useCallback)(()=>r.current?.takeOver(),[])}}var KD={401:`Please sign in again.`,403:`Incorrect PIN.`,413:`That recording was too long.`,429:`Too many attempts. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function qD(e,t){let n;try{n=await fetch(e,t)}catch{throw Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||KD[n.status]||`The request failed (${n.status}).`)}return await n.json()}var JD=(e,t)=>({method:e,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),YD={state:()=>qD(`/api/voice/enroll`,{}),sample:e=>qD(`/api/voice/enroll/sample`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e}),finish:e=>qD(`/api/voice/enroll/finish`,JD(`POST`,{pin:e})),cancel:async()=>{await qD(`/api/voice/enroll/cancel`,JD(`POST`,{}))},remove:async e=>{await qD(`/api/voice/enroll`,JD(`DELETE`,{pin:e}))}},XD=[`Friend, good evening. It is a pleasant day to get things done.`,`Open my projects and show me what changed today.`,`My voice is my key, so please remember it well.`,`Check the weather and read me the latest headlines.`,`Always protect the boss, and never trust a stranger.`],ZD=15e3;function QD({api:e=YD,createRecorder:t=e=>new BD(e),onClose:n,who:r}){let[i,a]=(0,l.useState)(null),[o,s]=(0,l.useState)(0),[c,u]=(0,l.useState)(null),[f,m]=(0,l.useState)(`record`),[h,g]=(0,l.useState)(!1),[_,v]=(0,l.useState)(!1),[y,b]=(0,l.useState)(null),[S,C]=(0,l.useState)(``),w=(0,l.useRef)(!0),T=(0,l.useRef)(null);(0,l.useEffect)(()=>(w.current=!0,e.state().then(e=>{w.current&&(a(e),s(e.samples))}).catch(e=>w.current&&b(e.message)),()=>{w.current=!1,T.current?.cancel(),T.current=null}),[e]);let E=(0,l.useCallback)(async()=>{let t=T.current;if(t){T.current=null,g(!1),v(!0);try{let n=await t.stop(),r=await e.sample(n);if(!w.current)return;s(r.count),u(r.note)}catch(e){w.current&&b(e.message)}finally{w.current&&v(!1)}}},[e]),D=async()=>{b(null),u(null);let e=t({maxMs:ZD,onLimit:()=>void E(),onError:()=>{T.current=null,w.current&&(g(!1),b(`The microphone stopped working. Try again.`))}});try{await e.start()}catch(e){w.current&&b(e.message);return}if(!w.current)return e.cancel();T.current=e,g(!0)},O=async e=>{b(null),v(!0);try{await e()}catch(e){w.current&&b(e.message)}finally{w.current&&(v(!1),C(``))}},k=async()=>{T.current?.cancel(),T.current=null,await e.cancel().catch(()=>{}),n()},A=i?.min??3,j=o%XD.length,ee=o<XD.length?`Phrase ${o+1} of ${XD.length}`:`Extra recording (${o} so far)`;return(0,p.jsxs)(`div`,{className:`approval enroll glass`,role:`dialog`,"aria-label":`Voice enrollment`,style:{pointerEvents:`auto`},children:[(0,p.jsx)(`div`,{className:`approval-head`,children:(0,p.jsx)(`span`,{className:`approval-title`,children:r?`Teach Friend ${r}'s voice`:`Teach Friend your voice`})}),f===`record`&&(0,p.jsxs)(p.Fragment,{children:[!r&&i?.enrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`Your voice is already saved. Saving a new one replaces it.`}),r&&(0,p.jsxs)(`p`,{className:`auth-note`,children:[`Hand the device to `,r,`. `,r,` reads each sentence aloud, close to the microphone, in a quiet room.`]}),(0,p.jsxs)(`p`,{className:`auth-note`,children:[ee,`. Press Record, read this aloud in a quiet room, then press Stop.`]}),(0,p.jsx)(`pre`,{className:`approval-summary`,"data-testid":`enroll-phrase`,style:{whiteSpace:`pre-wrap`},children:XD[j]}),(0,p.jsxs)(`div`,{role:`status`,className:`auth-note`,children:[o,` recorded`,o>=A?` — enough to save`:` — at least ${A} needed`,`.`,c?` ${c}`:``]}),y&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:y}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[h?(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,onClick:()=>void E(),children:`Stop`}):(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:_||!i||o>=(i?.max??8),onClick:()=>void D(),children:_?`Uploading…`:`Record`}),(0,p.jsx)(`button`,{type:`button`,style:d,disabled:h||_||o<A,onClick:()=>m(`pin-save`),children:r?`Save ${r}'s voice`:`Save my voice`}),!r&&i?.enrolled&&(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:h||_,onClick:()=>m(`pin-delete`),children:`Delete my voice`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>void k(),children:`Cancel`})]})]}),(f===`pin-save`||f===`pin-delete`)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:f===`pin-save`?r?`Enter your PIN to save ${r}'s voice.`:`Enter your PIN to save your voice.`:`Enter your PIN to delete your saved voice.`}),(0,p.jsx)(x,{pin:S,onChange:C,onSubmit:f===`pin-save`?()=>!_&&void O(async()=>{await e.finish(S),w.current&&m(`saved`)}):void 0}),y&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:y}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[f===`pin-save`?(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:_||S.length<6,onClick:()=>void O(async()=>{await e.finish(S),w.current&&m(`saved`)}),children:`Save`}):(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:_||S.length<6,onClick:()=>void O(async()=>{await e.remove(S),w.current&&m(`deleted`)}),children:`Delete`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>{C(``),b(null),m(`record`)},children:`Back`})]})]}),(f===`saved`||f===`deleted`)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:f===`saved`?r?`${r}'s voice is saved. From now on I will know when ${r} is talking.`:`Your voice is saved. From now on I will tell you apart from other speakers.`:`Your voice was deleted. Every voice is treated as yours until you enroll again.`}),(0,p.jsx)(`div`,{className:`approval-actions`,children:(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,onClick:n,children:`Done`})})]})]})}var $D=new Set([`INPUT`,`TEXTAREA`,`SELECT`,`BUTTON`,`A`,`SUMMARY`]),eO=new Set([`button`,`checkbox`,`switch`,`tab`,`menuitem`,`link`,`radio`,`option`,`textbox`,`combobox`,`slider`]),tO=e=>e instanceof HTMLElement&&($D.has(e.tagName)||e.isContentEditable||eO.has(e.getAttribute(`role`)??``)),nO=e=>e.code===`Space`||e.key===` `;function rO(e){let t=(0,l.useRef)(e);t.current=e,(0,l.useEffect)(()=>{let e=!1,n=n=>{!nO(n)||n.ctrlKey||n.metaKey||n.altKey||tO(n.target)||tO(document.activeElement)||(n.preventDefault(),!(n.repeat||e)&&(e=!0,t.current.pressStart()))},r=n=>{nO(n)&&e&&(e=!1,n.preventDefault(),t.current.pressEnd())},i=()=>{e=!1,t.current.blur()},a=()=>{document.hidden&&i()};return window.addEventListener(`keydown`,n),window.addEventListener(`keyup`,r),window.addEventListener(`blur`,i),document.addEventListener(`visibilitychange`,a),()=>{window.removeEventListener(`keydown`,n),window.removeEventListener(`keyup`,r),window.removeEventListener(`blur`,i),document.removeEventListener(`visibilitychange`,a)}},[])}function iO(e){let t=(0,l.useRef)(e);t.current=e,(0,l.useEffect)(()=>{let e=()=>t.current.unlock(),n=[`pointerdown`,`keydown`,`touchend`];for(let t of n)window.addEventListener(t,e,{passive:!0});return()=>{for(let t of n)window.removeEventListener(t,e)}},[])}function aO({onUseHere:e}){return(0,p.jsx)(`div`,{className:`elsewhere`,role:`alertdialog`,"aria-labelledby":`elsewhere-title`,"data-testid":`elsewhere`,children:(0,p.jsxs)(`div`,{className:`elsewhere-card`,children:[(0,p.jsx)(`h2`,{id:`elsewhere-title`,children:`Friend is open in another window`}),(0,p.jsx)(`p`,{children:`Friend works in one window at a time. Click “Use here” to use it in this window instead; the other one will stop.`}),(0,p.jsx)(`button`,{type:`button`,className:`elsewhere-btn`,onClick:e,autoFocus:!0,children:`Use here`})]})})}function oO(e,t,n){let r=Math.max(100,Math.round(e)),i=Math.max(100,Math.round(t));return{width:r,height:i,kind:r<=599?`phone`:n||r<1024?`tablet`:`desktop`,orientation:i>r?`portrait`:`landscape`,touch:n}}var sO=()=>typeof matchMedia==`function`&&matchMedia(`(pointer: coarse)`).matches;function cO(){return oO(window.innerWidth,window.innerHeight,sO())}var lO=(e,t)=>!!e&&e.width===t.width&&e.height===t.height&&e.kind===t.kind&&e.orientation===t.orientation&&e.touch===t.touch;function uO(e,t){let n=(0,l.useRef)(null),r=(0,l.useRef)(e);r.current=e,(0,l.useEffect)(()=>{if(t!==`open`){n.current=null;return}let e=()=>{let e=cO();lO(n.current,e)||(n.current=e,r.current({type:`ui.screen`,...e}))};e();let i=null,a=()=>{i&&clearTimeout(i),i=setTimeout(e,400)};return window.addEventListener(`resize`,a),window.addEventListener(`orientationchange`,a),()=>{i&&clearTimeout(i),window.removeEventListener(`resize`,a),window.removeEventListener(`orientationchange`,a)}},[t])}var dO={401:`Please sign in again.`,403:`Incorrect PIN.`,413:`That recording was too long.`,429:`Too many attempts. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function fO(e,t={}){let n;try{n=await fetch(e,t)}catch{throw Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||dO[n.status]||`The request failed (${n.status}).`)}return await n.json()}var pO=(e,t)=>({method:e,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),mO={overview:()=>fO(`/api/voice/people`),begin:e=>fO(`/api/voice/people/begin`,pO(`POST`,{name:e})),recording:{state:async()=>(await fO(`/api/voice/people`)).enrolling??{enrolled:!1,samples:0,min:3,max:8},sample:e=>fO(`/api/voice/people/sample`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e}),finish:e=>fO(`/api/voice/people/finish`,pO(`POST`,{pin:e})),cancel:async()=>{await fO(`/api/voice/people/cancel`,pO(`POST`,{}))},remove:async()=>{}},removePerson:async(e,t)=>{await fO(`/api/voice/people/${e}`,pO(`DELETE`,{pin:t}))}};function hO({api:e=mO,createRecorder:t,onClose:n}){let[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)({kind:`list`}),[s,c]=(0,l.useState)(``),[u,f]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(null),v=(0,l.useRef)(!0),y=(0,l.useCallback)(()=>{e.overview().then(e=>v.current&&i(e)).catch(e=>v.current&&_(e.message))},[e]);(0,l.useEffect)(()=>(v.current=!0,y(),()=>{v.current=!1}),[y]);let b=async()=>{_(null),h(!0);try{let t=await e.begin(s.trim());v.current&&o({kind:`record`,name:t.name})}catch(e){v.current&&_(e.message)}finally{v.current&&h(!1)}},S=async t=>{_(null),h(!0);try{if(await e.removePerson(t.id,u),!v.current)return;o({kind:`list`}),y()}catch(e){v.current&&_(e.message)}finally{v.current&&(h(!1),f(``))}};return a.kind===`record`?(0,p.jsx)(QD,{api:e.recording,who:a.name,...t?{createRecorder:t}:{},onClose:()=>{c(``),o({kind:`list`}),y()}}):(0,p.jsxs)(`div`,{className:`approval enroll glass`,role:`dialog`,"aria-label":`Family voices`,style:{pointerEvents:`auto`},children:[(0,p.jsx)(`div`,{className:`approval-head`,children:(0,p.jsx)(`span`,{className:`approval-title`,children:`Family voices`})}),a.kind===`list`&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:`Friend knows your voice. Add the people at home, so it knows who is talking and answers them by name. They can chat and ask for the weather, but cannot use your PC or see your private things.`}),r&&!r.ownerEnrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`First teach Friend your own voice (Esc, then Enroll my voice).`}),r&&r.people.length===0&&r.ownerEnrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`Nobody added yet.`}),r&&r.people.length>0&&(0,p.jsx)(`ul`,{className:`household-list`,"aria-label":`People Friend knows`,children:r.people.map(e=>(0,p.jsxs)(`li`,{className:`household-row`,children:[(0,p.jsx)(`span`,{children:e.name}),(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,onClick:()=>o({kind:`remove`,person:e}),"aria-label":`Remove ${e.name}`,children:`Remove`})]},e.id))}),r&&r.ownerEnrolled&&r.people.length<r.max&&(0,p.jsxs)(`label`,{className:`settings-field`,children:[(0,p.jsx)(`span`,{children:`Add a person`}),(0,p.jsx)(`input`,{value:s,maxLength:40,placeholder:`Name, for example Priya`,onChange:e=>c(e.target.value),onKeyDown:e=>e.key===`Enter`&&s.trim()&&!m&&void b()})]}),g&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:g}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[r&&r.ownerEnrolled&&r.people.length<r.max&&(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:m||!s.trim(),onClick:()=>void b(),children:`Record their voice`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:n,children:`Close`})]})]}),a.kind===`remove`&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`auth-note`,children:[`Enter your PIN to remove `,a.person.name,`’s voice. Friend will treat their voice as a stranger’s.`]}),(0,p.jsx)(x,{pin:u,onChange:f}),g&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:g}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:m||u.length<6,onClick:()=>void S(a.person),children:`Remove`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>{f(``),_(null),o({kind:`list`})},children:`Back`})]})]})]})}var gO=`▌▍▎▏█▓▒░<>/\\|+-=*#%&0123456789ABCDEF`;function _O(e,t,n=Math.random){let r=[...e];if(t>=1)return e;let i=Math.floor(r.length*Math.max(0,t));return r.map((e,t)=>t<i||e===` `?e:gO[Math.floor(n()*36)]).join(``)}var vO=e=>e.length===0?0:Math.min(24,Math.max(6,Math.ceil([...e].length/2)));function yO(e,t){let[n,r]=(0,l.useState)(e),i=(0,l.useRef)(e);return(0,l.useEffect)(()=>{if(!t||e===i.current){i.current=e,r(e);return}i.current=e;let n=vO(e);if(n===0){r(e);return}let a=0,o=setInterval(()=>{a++,r(_O(e,a/n)),a>=n&&clearInterval(o)},320/n);return()=>clearInterval(o)},[e,t]),n}function bO(e){let t=e.currentTarget,n=t.getBoundingClientRect(),r=document.createElement(`span`);r.className=`hud-ripple`;let i=Math.max(n.width,n.height)*2;r.style.width=r.style.height=`${i}px`,r.style.left=`${e.clientX-n.left-i/2}px`,r.style.top=`${e.clientY-n.top-i/2}px`,t.appendChild(r),r.addEventListener(`animationend`,()=>r.remove(),{once:!0}),setTimeout(()=>r.remove(),900)}function xO({items:e,animations:t,onAction:n}){let[r,i]=(0,l.useState)(null),a=(0,l.useRef)(void 0);if((0,l.useEffect)(()=>()=>clearTimeout(a.current),[]),e.length===0)return null;let o=e=>{t!==`off`&&(i(e.id),clearTimeout(a.current),a.current=setTimeout(()=>i(null),650)),n(e)};return(0,p.jsxs)(B,{id:`launcher`,label:`Quick launch`,wholeBox:!0,testId:`launcher`,className:`hud hud-launcher${t===`full`?` hud-boot`:``}`,children:[(0,p.jsx)(`div`,{className:`hud-kicker`,children:`Quick launch`}),(0,p.jsx)(`ul`,{className:`hud-stack`,children:e.map((e,n)=>(0,p.jsx)(`li`,{className:`hud-tab hud-cut${r===e.id?` engaged`:``}${t===`full`?` hud-boot`:``}`,style:{"--i":n+1},children:(0,p.jsxs)(`button`,{type:`button`,className:`hud-tab-main`,"aria-label":e.label,onPointerDown:t===`off`?void 0:bO,onClick:()=>o(e),children:[(0,p.jsx)(`span`,{className:`hud-icon`,"aria-hidden":`true`,children:e.icon}),(0,p.jsx)(`span`,{className:`hud-tab-label`,children:e.label}),(0,p.jsx)(`span`,{className:`hud-tab-engaged`,"aria-hidden":`true`,children:`ENGAGED`}),(0,p.jsx)(`span`,{className:`hud-sweep`,"aria-hidden":`true`}),(0,p.jsx)(`span`,{className:`hud-scan`,"aria-hidden":`true`})]})},e.id))})]})}var SO=(e,t=18)=>(0,p.jsx)(`svg`,{width:t,height:t,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.8`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:e}),CO=()=>SO((0,p.jsx)(`path`,{d:`M7 4.5v15l12-7.5z`,fill:`currentColor`})),wO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`rect`,{x:`6`,y:`4.5`,width:`4`,height:`15`,fill:`currentColor`}),(0,p.jsx)(`rect`,{x:`14`,y:`4.5`,width:`4`,height:`15`,fill:`currentColor`})]})),TO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M5 5v14l10-7z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M18 5v14`})]})),EO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M19 5v14L9 12z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M6 5v14`})]})),DO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M3 7h3.5c3 0 4 2 5.5 5s2.500 5 5.500 5H21`}),(0,p.jsx)(`path`,{d:`M3 17h3.5c1.500 0 2.500-.6 3.400-1.800M13.500 8.800C14.500 7.600 15.500 7 17 7h4`}),(0,p.jsx)(`path`,{d:`m18.500 4.500 2.500 2.500-2.500 2.500M18.500 14.500l2.500 2.500-2.500 2.500`})]})),OO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M17 3l3 3-3 3`}),(0,p.jsx)(`path`,{d:`M4 11V9a3 3 0 0 1 3-3h13M7 21l-3-3 3-3`}),(0,p.jsx)(`path`,{d:`M20 13v2a3 3 0 0 1-3 3H4`})]})),kO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M4 9.500v5h3.500L12 18.500v-13L7.500 9.500z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M15.500 9a4 4 0 0 1 0 6M18 6.500a7.500 7.500 0 0 1 0 11`})]})),AO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M4 9.500v5h3.500L12 18.500v-13L7.500 9.500z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`m16 9 5 6M21 9l-5 6`})]})),jO=()=>SO((0,p.jsx)(`path`,{d:`M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5`})),MO=()=>SO((0,p.jsx)(`path`,{d:`M9 4v5H4M15 4v5h5M9 20v-5H4M15 20v-5h5`})),NO=()=>SO((0,p.jsx)(`path`,{d:`M6 6l12 12M18 6 6 18`})),PO=()=>SO((0,p.jsx)(`path`,{d:`M9 18V6l10-2v12`}),22),FO=56,IO=()=>({bars:new Float32Array(FO),bass:0,left:0,right:0});function LO(e,t,n,r,i){let a=n?.82:.9;if(t&&n){t.getByteFrequencyData(i);let n=Math.min(i.length,96);for(let t=0;t<FO;t++){let r=Math.min(n-1,Math.floor((t/FO)**1.6*n));e.bars[t]=Math.max((i[r]??0)/255,e.bars[t]*a)}}else if(n)for(let t=0;t<FO;t++)e.bars[t]=Math.max(.12+.28*Math.abs(Math.sin(r/420+t*.55)*Math.cos(r/900+t*.21)),e.bars[t]*a);else for(let t=0;t<FO;t++)e.bars[t]=e.bars[t]*a;let o=0;for(let t=0;t<6;t++)o+=e.bars[t];e.bass=Math.min(1,o/6*1.15);let s=0,c=0;for(let t=0;t<FO/2;t++)s+=e.bars[t],c+=e.bars[t+FO/2];e.left=Math.min(1,s/(FO/2)*1.6),e.right=Math.min(1,c/(FO/2)*3.2)}function RO({progress:e,playing:t,cover:n,analyser:r,levels:i,visualizer:a,animate:o,size:s}){let c=(0,l.useRef)(null),u=(0,l.useRef)(null),d=(0,l.useRef)(new Uint8Array(new ArrayBuffer(128)));(0,l.useEffect)(()=>{let e=c.current,n=e?.getContext(`2d`);if(!e||!n||!o)return;let l=0,f=Math.min(2,window.devicePixelRatio||1);e.width=e.height=Math.round(s*f);let p=getComputedStyle(e).getPropertyValue(`--accent`).trim()||`#3fd8ff`,m=e=>{if(LO(i,r,t,e,d.current),u.current?.style.setProperty(`--bass`,i.bass.toFixed(3)),n.setTransform(f,0,0,f,0,0),n.clearRect(0,0,s,s),a){let e=s/2,t=s*.335,r=s*.135;n.lineCap=`round`,n.lineWidth=Math.max(1.5,s/90);for(let a=0;a<FO;a++){let o=a/FO*Math.PI*2-Math.PI/2,s=i.bars[a],c=2+s*r;n.strokeStyle=p,n.globalAlpha=.35+s*.65,n.beginPath(),n.moveTo(e+Math.cos(o)*t,e+Math.sin(o)*t),n.lineTo(e+Math.cos(o)*(t+c),e+Math.sin(o)*(t+c)),n.stroke()}n.globalAlpha=1}(t||!i.bars.every(e=>e<.01)||a)&&(l=requestAnimationFrame(m))};return l=requestAnimationFrame(m),()=>cancelAnimationFrame(l)},[r,t,a,o,s,i]);let f=Math.max(0,Math.min(1,e))*100;return(0,p.jsxs)(`div`,{ref:u,className:`hud-dial${t?` playing`:``}`,style:{width:s,height:s},role:`img`,"aria-label":`Playback dial`,children:[(0,p.jsxs)(`svg`,{className:`hud-dial-svg`,viewBox:`0 0 200 200`,"aria-hidden":`true`,children:[(0,p.jsx)(`circle`,{className:`hud-dial-ticks`,cx:`100`,cy:`100`,r:`96`}),(0,p.jsx)(`circle`,{className:`hud-dial-track`,cx:`100`,cy:`100`,r:`88`}),(0,p.jsx)(`circle`,{className:`hud-dial-arc`,cx:`100`,cy:`100`,r:`88`,pathLength:`100`,strokeDasharray:`${f} 100`,transform:`rotate(-90 100 100)`}),(0,p.jsx)(`circle`,{className:`hud-dial-inner`,cx:`100`,cy:`100`,r:`62`}),(0,p.jsxs)(`g`,{className:`hud-needle`,children:[(0,p.jsx)(`line`,{x1:`100`,y1:`100`,x2:`100`,y2:`14`}),(0,p.jsx)(`circle`,{cx:`100`,cy:`14`,r:`2.500`})]})]}),(0,p.jsx)(`canvas`,{ref:c,className:`hud-spectrum`,style:{width:s,height:s},"aria-hidden":`true`}),(0,p.jsx)(`div`,{className:`hud-cover`,style:n?{backgroundImage:`url("${n}")`}:void 0,children:!n&&(0,p.jsx)(PO,{})})]})}var zO=e=>{let t=Math.max(0,Math.floor(Number.isFinite(e)?e:0));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`},BO=new Map;function VO(e){let[t,n]=(0,l.useState)(e?BO.get(e)??!1:!1);return(0,l.useEffect)(()=>{if(!e)return n(!1);if(BO.has(e))return n(BO.get(e));let t=!0,r=new Image;return r.onload=()=>{BO.set(e,!0),t&&n(!0)},r.onerror=()=>{BO.set(e,!1),t&&n(!1)},r.src=`/api/music/cover/${e}`,()=>{t=!1}},[e]),e&&t?`/api/music/cover/${e}`:null}async function HO(e,t){let n=await fetch(`/api/music/library?q=${encodeURIComponent(e)}&limit=${t}`);return n.ok?await n.json():{tracks:[],total:0}}var UO=e=>({id:e.id,title:e.title,artist:e.artist,album:e.album,durationSec:e.durationSec});function WO({levels:e,animate:t,side:n}){let r=(0,l.useRef)(null);return(0,l.useEffect)(()=>{if(!t)return;let i=0,a=r.current,o=()=>{if(a){let t=n===`left`?e.left:e.right,r=Math.round(t*12);a.querySelectorAll(`i`).forEach((e,t)=>e.classList.toggle(`on`,t<r))}i=requestAnimationFrame(o)};return i=requestAnimationFrame(o),()=>cancelAnimationFrame(i)},[e,t,n]),(0,p.jsx)(`div`,{ref:r,className:`hud-levels ${n}`,"aria-hidden":`true`,children:Array.from({length:12},(e,t)=>(0,p.jsx)(`i`,{},t))})}function GO({player:e,anim:t}){let{state:n,dispatch:r}=e,i=(0,l.useCallback)(async()=>{if(n.queue.length>0)return r({type:`resume`});let e=await HO(``,500);r({type:`play`,tracks:e.tracks.map(UO),mode:`replace`,...n.shuffle?{shuffle:!0}:{}})},[n.queue.length,n.shuffle,r]),a=e=>n=>{t!==`off`&&bO(n),e()};return(0,p.jsxs)(`div`,{className:`hud-controls`,role:`group`,"aria-label":`Player controls`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Shuffle`,"aria-pressed":n.shuffle,title:`Shuffle`,onClick:()=>r({type:`shuffle`}),children:(0,p.jsx)(DO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Previous track`,title:`Previous`,onPointerDown:a(()=>{}),onClick:()=>r({type:`previous`}),children:(0,p.jsx)(EO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn hud-btn-main`,"aria-label":n.playing?`Pause`:`Play`,title:n.playing?`Pause`:`Play`,onPointerDown:a(()=>{}),onClick:()=>n.playing?r({type:`pause`}):void i(),children:n.playing?(0,p.jsx)(wO,{}):(0,p.jsx)(CO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Next track`,title:`Next`,onPointerDown:a(()=>{}),onClick:()=>r({type:`next`}),children:(0,p.jsx)(TO,{})}),(0,p.jsxs)(`button`,{type:`button`,className:`hud-btn${n.repeat===`off`?``:` on`}`,"aria-label":`Repeat: ${n.repeat}`,title:`Repeat: ${n.repeat}`,onClick:()=>r({type:`repeat`,mode:n.repeat===`off`?`all`:n.repeat===`all`?`one`:`off`}),children:[(0,p.jsx)(OO,{}),n.repeat===`one`&&(0,p.jsx)(`sup`,{children:`1`})]})]})}function KO({player:e}){let{state:t,dispatch:n}=e,r=t.duration>0?t.position/t.duration*100:0;return(0,p.jsxs)(`div`,{className:`hud-timeline`,children:[(0,p.jsx)(`span`,{className:`hud-time`,children:zO(t.position)}),(0,p.jsx)(`input`,{type:`range`,className:`hud-range`,"aria-label":`Position`,min:0,max:Math.max(1,Math.floor(t.duration)),step:1,value:Math.min(Math.floor(t.position),Math.max(1,Math.floor(t.duration))),style:{"--fill":`${r}%`},disabled:t.duration<=0,onChange:e=>n({type:`seek`,seconds:Number(e.target.value)})}),(0,p.jsxs)(`span`,{className:`hud-time`,children:[`-`,zO(Math.max(0,t.duration-t.position))]})]})}function qO({player:e}){let{state:t,dispatch:n}=e;return(0,p.jsxs)(`div`,{className:`hud-volume`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":t.muted?`Unmute`:`Mute`,onClick:()=>n({type:`mute`}),children:t.muted||t.volume===0?(0,p.jsx)(AO,{}):(0,p.jsx)(kO,{})}),(0,p.jsx)(`input`,{type:`range`,className:`hud-range`,"aria-label":`Volume`,min:0,max:100,value:t.muted?0:t.volume,style:{"--fill":`${t.muted?0:t.volume}%`},onChange:e=>n({type:`volume`,level:Number(e.target.value)})})]})}function JO({player:e,anim:t}){let{state:n,dispatch:r}=e,[i,a]=(0,l.useState)(n.queue.length?`queue`:`library`),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(null);(0,l.useEffect)(()=>{if(i!==`library`)return;let e=!0,t=setTimeout(()=>void HO(o,100).then(t=>e&&u(t)),o?250:0);return()=>{e=!1,clearTimeout(t)}},[i,o]);let d=i===`queue`?n.queue.map((e,t)=>({track:e,index:t})):(c?.tracks??[]).map((e,t)=>({track:UO(e),index:t}));return(0,p.jsxs)(`div`,{className:`hud-playlist`,children:[(0,p.jsxs)(`div`,{className:`hud-tabs`,role:`tablist`,children:[[`queue`,`library`].map(e=>(0,p.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===e,className:`hud-chip${i===e?` on`:``}`,onClick:()=>a(e),children:e===`queue`?`Queue (${n.queue.length})`:`Library`},e)),i===`queue`&&n.queue.length>0&&(0,p.jsx)(`button`,{type:`button`,className:`hud-chip`,onClick:()=>r({type:`clear`}),children:`Clear`})]}),i===`library`&&(0,p.jsx)(`input`,{className:`hud-search`,type:`search`,placeholder:`Search title, artist or album`,"aria-label":`Search the music`,value:o,onChange:e=>s(e.target.value)}),(0,p.jsxs)(`ul`,{className:`hud-list`,children:[d.length===0&&(0,p.jsx)(`li`,{className:`hud-empty`,children:i===`queue`?`The queue is empty.`:c?`No music matches.`:`Loading…`}),d.map(({track:e,index:a},o)=>{let s=i===`queue`&&a===n.index;return(0,p.jsxs)(`li`,{className:`hud-tab hud-cut${s?` current`:``}${t===`full`?` hud-boot`:``}`,style:{"--i":Math.min(o,12)},children:[(0,p.jsxs)(`button`,{type:`button`,className:`hud-tab-main`,"aria-current":s?`true`:void 0,onPointerDown:t===`off`?void 0:bO,onClick:()=>r(i===`queue`?{type:`jump`,index:a}:{type:`play`,tracks:(c?.tracks??[]).map(UO),mode:`replace`,start:a}),children:[(0,p.jsx)(`span`,{className:`hud-tab-title`,children:e.title}),(0,p.jsx)(`small`,{children:e.artist||e.album})]}),i===`library`&&(0,p.jsx)(`button`,{type:`button`,className:`hud-mini`,"aria-label":`Add ${e.title} to the queue`,title:`Add to the queue`,onClick:()=>r({type:`play`,tracks:[e],mode:`add`}),children:`+`}),i===`queue`&&(0,p.jsx)(`button`,{type:`button`,className:`hud-mini`,"aria-label":`Remove ${e.title} from the queue`,title:`Remove`,onClick:()=>r({type:`remove`,index:a}),children:`×`})]},`${e.id}-${a}`)})]})]})}function YO({player:e,music:t,animations:n}){let{state:r,dispatch:i,current:a,blocked:o,analyser:s,unlock:c}=e,u=(0,l.useMemo)(IO,[]),d=VO(a?.id),f=r.view===`full`,m=yO(a?.title??``,n===`full`);if(!t?.folderSet||r.view===`hidden`)return null;let h=r.duration>0?r.position/r.duration:0,g=n!==`off`;return(0,p.jsxs)(B,{id:`music`,label:`Music player`,wholeBox:!0,testId:`music`,className:`hud hud-music hud-cut ${f?`full`:`mini`}${r.playing?` playing`:``}${n===`full`?` hud-boot`:``}`,children:[(0,p.jsxs)(`header`,{className:`hud-music-head`,children:[(0,p.jsx)(`span`,{className:`hud-kicker`,children:`Media player`}),(0,p.jsxs)(`span`,{className:`hud-head-actions`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":f?`Smaller player`:`Bigger player`,title:f?`Smaller`:`Bigger`,onClick:()=>i({type:`view`,view:f?`mini`:`full`}),children:f?(0,p.jsx)(MO,{}):(0,p.jsx)(jO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Hide the player`,title:`Hide (the music keeps playing)`,onClick:()=>i({type:`view`,view:`hidden`}),children:(0,p.jsx)(NO,{})})]})]}),(0,p.jsxs)(`div`,{className:`hud-music-body`,children:[(0,p.jsxs)(`div`,{className:`hud-music-left`,children:[f&&(0,p.jsx)(WO,{levels:u,animate:g,side:`left`}),(0,p.jsx)(RO,{progress:h,playing:r.playing,cover:d,analyser:s,levels:u,visualizer:t.visualizer,animate:g,size:f?250:112}),f&&(0,p.jsx)(WO,{levels:u,animate:g,side:`right`})]}),(0,p.jsxs)(`div`,{className:`hud-music-main`,children:[(0,p.jsxs)(`div`,{className:`hud-now`,"aria-live":`polite`,children:[(0,p.jsx)(`b`,{className:`hud-title`,children:a?m:`Nothing playing`}),(0,p.jsx)(`small`,{className:`hud-sub`,children:a?[a.artist,a.album].filter(Boolean).join(` — `):`Press play, or ask for some music.`})]}),(0,p.jsx)(KO,{player:e}),(0,p.jsx)(GO,{player:e,anim:n}),f&&(0,p.jsx)(qO,{player:e}),o&&(0,p.jsx)(`button`,{type:`button`,className:`hud-unlock`,onClick:c,children:`Tap to enable sound`})]}),f&&(0,p.jsx)(JO,{player:e,anim:n})]})]})}var XO=2e3,ZO=3,QO=e=>({queue:[],index:-1,playing:!1,position:0,duration:0,volume:e.volume,muted:!1,shuffle:e.shuffle,repeat:e.repeat,view:e.view});function $O(e,t=Math.random){let n=[...e];for(let e=n.length-1;e>0;e--){let r=Math.floor(t()*(e+1));[n[e],n[r]]=[n[r],n[e]]}return n}var ek=(e,t,n)=>Math.min(n,Math.max(t,e)),tk=(e,t,n)=>({...e,index:t,playing:n,position:0,duration:0});function nk(e,t,n={}){let r=n.shuffle??$O,i=e.queue.length-1;switch(t.type){case`play`:{if(t.tracks.length===0)return e;let n=t.tracks.slice(0,XO);if(t.mode===`replace`){let i=t.shuffle?r(n):n;return{...tk(e,t.shuffle?0:ek(t.start??0,0,i.length-1),!0),queue:i,shuffle:t.shuffle?!0:e.shuffle}}if(e.queue.length===0)return{...tk(e,0,!0),queue:n};let i=t.mode===`next`?e.index+1:e.queue.length;return{...e,queue:[...e.queue.slice(0,i),...n,...e.queue.slice(i)].slice(0,XO)}}case`next`:return i<0?e:e.index<i?tk(e,e.index+1,!0):e.repeat===`off`?{...e,playing:!1,position:0}:tk(e,0,!0);case`previous`:return i<0?e:e.position>ZO?{...e,position:0}:e.index>0?tk(e,e.index-1,e.playing||!0):e.repeat===`all`?tk(e,i,!0):{...e,position:0};case`ended`:return i<0?e:e.repeat===`one`?tk(e,e.index,!0):e.index<i?tk(e,e.index+1,!0):e.repeat===`all`?tk(e,0,!0):{...e,playing:!1,position:0};case`failed`:return i<0?e:e.index<i?tk(e,e.index+1,!0):{...e,playing:!1,position:0};case`pause`:return e.playing?{...e,playing:!1}:e;case`resume`:return e.index>=0&&!e.playing?{...e,playing:!0}:e;case`toggle`:return e.index<0?e:{...e,playing:!e.playing};case`stop`:return{...e,playing:!1,position:0};case`volume`:{let n=typeof t.level==`number`?Math.round(t.level):typeof t.delta==`number`?e.volume+Math.round(t.delta):e.volume;return{...e,volume:ek(n,0,100),muted:typeof t.level==`number`||(t.delta??0)>0?!1:e.muted}}case`mute`:return{...e,muted:t.on??!e.muted};case`seek`:{let n=typeof t.seconds==`number`?t.seconds:typeof t.percent==`number`?e.duration*ek(t.percent,0,100)/100:e.position;return{...e,position:ek(n,0,e.duration>0?e.duration:Math.max(n,0))}}case`repeat`:return{...e,repeat:t.mode};case`shuffle`:{if(!(t.on??!e.shuffle))return{...e,shuffle:!1};let n=e.queue.slice(0,e.index+1);return{...e,shuffle:!0,queue:[...n,...r(e.queue.slice(e.index+1))]}}case`view`:return{...e,view:t.view};case`remove`:{if(!Number.isInteger(t.index)||t.index<0||t.index>i)return e;let n=e.queue.filter((e,n)=>n!==t.index);return n.length===0?{...e,queue:n,index:-1,playing:!1,position:0,duration:0}:t.index<e.index?{...e,queue:n,index:e.index-1}:t.index>e.index?{...e,queue:n}:t.index<n.length?{...tk(e,t.index,e.playing),queue:n}:e.repeat===`all`?{...tk(e,0,e.playing),queue:n}:{...e,queue:n,index:n.length-1,playing:!1,position:0}}case`clear`:return{...e,queue:[],index:-1,playing:!1,position:0,duration:0};case`jump`:return Number.isInteger(t.index)&&t.index>=0&&t.index<=i?tk(e,t.index,!0):e;case`time`:return{...e,position:Math.max(0,t.position),duration:Math.max(0,t.duration)}}}var rk=(e,t)=>nk(e,t),ik=`friend.music`,ak=1e3,ok=1.5,sk=()=>{try{return JSON.parse(localStorage.getItem(ik)??`{}`)}catch{return{}}},ck=e=>{try{localStorage.setItem(ik,JSON.stringify({volume:e.volume,muted:e.muted,shuffle:e.shuffle,repeat:e.repeat}))}catch{}};function lk(e){switch(e.action){case`play`:return{type:`play`,tracks:e.tracks??[],mode:e.mode===`add`||e.mode===`next`?e.mode:`replace`,...e.shuffle?{shuffle:!0}:{}};case`pause`:case`resume`:case`toggle`:case`stop`:case`next`:case`previous`:return{type:e.action};case`seek`:return{type:`seek`,...e.seconds===void 0?{}:{seconds:e.seconds},...e.percent===void 0?{}:{percent:e.percent}};case`volume`:return{type:`volume`,...e.level===void 0?{}:{level:e.level},...e.delta===void 0?{}:{delta:e.delta}};case`mute`:return{type:`mute`,...e.on===void 0?{}:{on:e.on}};case`shuffle`:return{type:`shuffle`,...e.on===void 0?{}:{on:e.on}};case`repeat`:return e.mode===`off`||e.mode===`all`||e.mode===`one`?{type:`repeat`,mode:e.mode}:null;case`view`:return e.view?{type:`view`,view:e.view}:null;case`queue.remove`:return e.index===void 0?null:{type:`remove`,index:e.index};case`queue.clear`:return{type:`clear`};default:return null}}function uk({music:e,cmd:t,send:n,connection:r,createAudio:i}){let[a,o]=(0,l.useReducer)(rk,void 0,()=>{let e=sk();return QO({volume:e.volume??70,shuffle:e.shuffle??!1,repeat:e.repeat??`all`,view:`mini`})}),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(null),f=(0,l.useRef)(null),p=(0,l.useRef)(!1),m=(0,l.useRef)(a);m.current=a;let h=(0,l.useRef)(!1),g=(0,l.useRef)(null),_=(0,l.useRef)(0),v=(0,l.useRef)(!1);(0,l.useEffect)(()=>{if(!e||v.current)return;v.current=!0;let t=sk();o({type:`volume`,level:t.volume??e.volume}),o({type:`repeat`,mode:t.repeat??e.repeat}),(t.shuffle??e.shuffle)&&o({type:`shuffle`,on:!0}),o({type:`view`,view:e.startView}),t.muted&&o({type:`mute`,on:!0})},[e]);let y=()=>{if(!f.current){let e=i?i():new Audio;e.preload=`auto`,f.current=e}return f.current},b=(0,l.useRef)(!1),x=(0,l.useCallback)(()=>{let e=f.current;if(e&&e.src){b.current=!0;try{let t=e.play();t&&typeof t.then==`function`?t.then(()=>{b.current=!1,c(!1)},()=>{b.current=!1,c(!0)}):(b.current=!1,c(!1))}catch{b.current=!1,c(!0)}S.current||C()}},[]),S=(0,l.useRef)(!1),C=()=>{let e=f.current,t=typeof window<`u`?window.AudioContext??window.webkitAudioContext:void 0;if(e&&t&&typeof e.play==`function`)try{let n=new t,r=n.createMediaElementSource(e),i=n.createAnalyser();i.fftSize=256,i.smoothingTimeConstant=.82,r.connect(i),i.connect(n.destination),S.current=!0,d(i)}catch{S.current=!0}};(0,l.useEffect)(()=>{let e=y(),t=0,n=()=>{let n=Date.now();n-t<250||(t=n,o({type:`time`,position:e.currentTime||0,duration:Number.isFinite(e.duration)?e.duration:0}))},r=()=>o({type:`time`,position:e.currentTime||0,duration:Number.isFinite(e.duration)?e.duration:0}),i=()=>o({type:`ended`}),a=()=>o({type:`failed`});return e.addEventListener(`timeupdate`,n),e.addEventListener(`loadedmetadata`,r),e.addEventListener(`durationchange`,r),e.addEventListener(`ended`,i),e.addEventListener(`error`,a),()=>{e.removeEventListener(`timeupdate`,n),e.removeEventListener(`loadedmetadata`,r),e.removeEventListener(`durationchange`,r),e.removeEventListener(`ended`,i),e.removeEventListener(`error`,a),e.pause()}},[]);let w=a.index>=0?a.queue[a.index]??null:null;(0,l.useEffect)(()=>{let e=f.current;if(!e)return;let t=w?.id??null;if(t!==g.current){if(g.current=t,!t){e.pause(),e.src=``;return}e.src=`/api/music/track/${t}`,a.playing&&x()}},[w?.id,a.playing,x]),(0,l.useEffect)(()=>{let e=f.current;e&&e.src&&(a.playing&&e.paused&&!p.current&&!b.current?x():!a.playing&&!e.paused&&e.pause())},[a.playing,a.position,x]),(0,l.useEffect)(()=>{let e=f.current;e&&(e.volume=a.volume/100,e.muted=a.muted)},[a.volume,a.muted]),(0,l.useEffect)(()=>{let e=f.current;e&&e.src&&Math.abs((e.currentTime||0)-a.position)>ok&&(e.currentTime=a.position)},[a.position]),(0,l.useEffect)(()=>ck(a),[a.volume,a.muted,a.shuffle,a.repeat]),(0,l.useEffect)(()=>{if(!t||t.n===_.current)return;_.current=t.n;let e=lk(t.command);e&&o(e)},[t]),(0,l.useEffect)(()=>{let e=()=>{h.current=!0,p.current&&x()};return window.addEventListener(`pointerdown`,e,{passive:!0}),window.addEventListener(`keydown`,e),()=>{window.removeEventListener(`pointerdown`,e),window.removeEventListener(`keydown`,e)}},[x]),p.current=s;let T=(0,l.useRef)(0);return(0,l.useEffect)(()=>{if(r!==`open`)return;let e=()=>{let e=m.current,t=e.index>=0?e.queue[e.index]:void 0;T.current=Date.now(),n({type:`music.state`,state:{playing:e.playing,trackId:t?.id??null,title:t?.title??``,artist:t?.artist??``,album:t?.album??``,position:e.position,duration:e.duration,volume:e.volume,muted:e.muted,shuffle:e.shuffle,repeat:e.repeat,view:e.view,queue:e.queue.slice(0,50).map(e=>({id:e.id,title:e.title.slice(0,200)})),index:e.index,active:(typeof document>`u`||document.visibilityState===`visible`)&&h.current}})};e();let t=setInterval(()=>a.playing&&Date.now()-T.current>=ak&&e(),ak);return()=>clearInterval(t)},[r,w?.id,a.playing,a.volume,a.muted,a.shuffle,a.repeat,a.view,a.queue.length,a.index]),(0,l.useEffect)(()=>{let e=typeof navigator<`u`?navigator.mediaSession:void 0;if(e)try{w&&typeof MediaMetadata<`u`&&(e.metadata=new MediaMetadata({title:w.title,artist:w.artist,album:w.album,artwork:[{src:`/api/music/cover/${w.id}`}]})),e.playbackState=a.playing?`playing`:w?`paused`:`none`,e.setActionHandler(`play`,()=>o({type:`resume`})),e.setActionHandler(`pause`,()=>o({type:`pause`})),e.setActionHandler(`previoustrack`,()=>o({type:`previous`})),e.setActionHandler(`nexttrack`,()=>o({type:`next`})),e.setActionHandler(`seekto`,e=>typeof e.seekTime==`number`&&o({type:`seek`,seconds:e.seekTime}))}catch{}},[w?.id,a.playing]),{state:a,dispatch:o,current:w,blocked:s,analyser:u,unlock:x,audio:f}}function dk({onSignedOut:e}){let{state:t,send:n,dispatch:r,voice:i,useHere:a}=GD(e);rO(i),iO(i),uO(n,t.connection);let[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(!1),[d,f]=(0,l.useState)(!1),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(void 0),[v,y]=(0,l.useState)(null),[b,x]=(0,l.useState)(!1),[S,C]=(0,l.useState)(0),[w,T]=(0,l.useState)(null),E=de(t.view),D=uk({music:t.music,cmd:t.musicCmd,send:n,connection:t.connection}),O=t.hud?.animations??`full`,k=e=>{let{type:t,value:r}=e.action;if(t===`url`)window.open(r,`_blank`,`noopener,noreferrer`);else if(t===`prompt`)n({type:`chat.send`,text:r});else if(t===`music`){let e=lk({action:r});e&&D.dispatch(e)}else r===`plugins`?h(!0):r===`settings`?y(`model`):r===`chat`||r===`tasks`?E.toggle(r,!0):r===`music`&&(E.toggle(`music`,!0),D.state.view===`hidden`&&D.dispatch({type:`view`,view:`mini`}))},j=(0,l.useMemo)(()=>o?{...t,objects:[],captions:``}:t,[o,t]),ee=(0,l.useRef)(!1);(0,l.useEffect)(()=>{ee.current||!t.voice.available||t.voice.enrolled||(ee.current=!0,r({type:`alert.add`,level:`info`,text:`Voice recognition is not set up. Press Esc, then Enroll my voice.`}))},[t.voice.available,t.voice.enrolled,r]);let M=ne(),N=(0,l.useRef)(!1);(0,l.useEffect)(()=>{if(!M||N.current||t.connection!==`open`)return;N.current=!0;let e=!1;try{e=localStorage.getItem(`friend.touchHint`)===`1`,localStorage.setItem(`friend.touchHint`,`1`)}catch{}e||r({type:`alert.add`,level:`info`,text:`Hold the round mic button to talk, or tap it once to start and again to send. The keyboard button types; the menu button opens settings.`})},[M,t.connection,r]);let P=t.uiOpen?.n??0,te=t.uiOpen?.integration;(0,l.useEffect)(()=>{P!==0&&(_(te),h(!0))},[P,te]);let L=(0,l.useRef)(!1);(0,l.useEffect)(()=>{L.current||t.connection!==`open`||(L.current=!0,fetch(`/api/history`).then(e=>e.ok?e.json():[]).then(e=>r({type:`chat.seed`,lines:e})).catch(()=>{}))},[t.connection,r]),(0,l.useEffect)(()=>{t.connection===`open`&&n({type:`ui.panels`,open:[...E.show.chat?[`chat`]:[],...E.show.tasks?[`tasks`]:[]]})},[t.connection,E.show.chat,E.show.tasks,n]);let re=(0,l.useRef)(!1);(0,l.useEffect)(()=>{t.viewKnown&&t.view===`minimal`&&!re.current&&(re.current=!0,r({type:`alert.add`,level:`info`,text:`The view is Minimal, so the status line and clock are hidden. Press Esc, then View, to bring them back.`}))},[t.viewKnown,t.view,r]);let ie=e=>{ze.save({view:e}).catch(e=>r({type:`alert.add`,level:`warn`,text:e.message}))},ae=(0,l.useMemo)(()=>F({notify:e=>r({type:`alert.add`,level:`info`,text:e}),openSettings:()=>y(`model`),openLook:()=>y(`look`),openConnectors:()=>x(!0),openPlugins:()=>h(!0),openVoice:t.voice.available?()=>u(!0):null,muted:o,setMuted:s,cameraOn:t.camera.enabled,setCamera:e=>r({type:`camera.enable`,value:e}),clearScreen:()=>{for(let e of t.objects)n({type:`stage.event`,objectId:e.id,event:`dismiss`})},statusLine:()=>Ee({connection:t.connection,deviceOnline:t.deviceOnline,approval:t.approval,voiceMode:t.voice.mode,busy:t.busy,activity:t.activity}).text,endSession:t=>{fetch(t===`lock`?`/api/lock`:`/api/logout`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).catch(()=>{}).finally(e)},panelOn:e=>E.show[e],setPanel:(e,t)=>E.toggle(e,t),view:t.view,setView:ie,openHelp:T,resetLayout:()=>{ue(),window.location.reload()}}),[r,n,o,e,E.show,E.toggle,t.view,t.voice.available,t.voice.mode,t.camera.enabled,t.objects,t.connection,t.deviceOnline,t.approval,t.busy,t.activity]);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(kT,{state:j,send:n,dispatch:r,voice:i,slash:ae,onMenu:()=>C(e=>e+1)}),(0,p.jsxs)(ke,{approval:t.approval,challenge:t.challenge,cameraStream:t.camera.stream,alerts:t.alerts,connection:t.connection,deviceOnline:t.deviceOnline,voiceMode:t.voice.mode,busy:t.busy,activity:t.activity,showStatus:t.viewKnown&&E.show.status,showClock:t.viewKnown&&E.show.clock,profile:t.viewKnown&&E.show.profile?{ownerName:t.ownerName,speaker:t.speaker}:null,assistantName:t.assistantName,hud:t.hud,send:n,dispatch:r,children:[t.viewKnown&&E.show.chat&&(0,p.jsx)(fe,{lines:t.chat,live:t.chatLive,onSend:e=>n({type:`chat.send`,text:e}),onClose:()=>E.toggle(`chat`,!1)}),t.viewKnown&&E.show.tasks&&(0,p.jsx)(he,{busy:t.busy,onClose:()=>E.toggle(`tasks`,!1)}),t.viewKnown&&E.show.launcher&&t.hud&&(0,p.jsx)(xO,{items:t.hud.launcher,animations:O,onAction:k}),t.viewKnown&&E.show.music&&(0,p.jsx)(YO,{player:D,music:t.music,animations:O}),c&&(0,p.jsx)(QD,{onClose:()=>u(!1)}),d&&(0,p.jsx)(hO,{onClose:()=>f(!1)}),m&&(0,p.jsx)(Fu,{...g?{initialConfigure:g}:{},onClose:()=>{h(!1),_(void 0)}}),v&&(0,p.jsx)(Ab,{initialTab:v,onClose:()=>y(null)}),b&&(0,p.jsx)(A,{onClose:()=>x(!1)}),w&&(0,p.jsx)(I,{commands:w,onClose:()=>T(null)})]}),(0,p.jsx)(V,{muted:o,onToggleMute:()=>s(e=>!e),onSignedOut:e,voiceAvailable:t.voice.available,voiceEnrolled:t.voice.enrolled,onEnroll:()=>u(!0),onHousehold:()=>f(!0),onPlugins:()=>h(!0),onSettings:()=>y(`model`),onConnectors:()=>x(!0),cameraOn:t.camera.enabled,onToggleCamera:()=>r({type:`camera.enable`,value:!t.camera.enabled}),chatOn:E.show.chat,onToggleChat:()=>E.toggle(`chat`),tasksOn:E.show.tasks,onToggleTasks:()=>E.toggle(`tasks`),musicOn:E.show.music,onToggleMusic:()=>E.toggle(`music`),launcherOn:E.show.launcher,onToggleLauncher:()=>E.toggle(`launcher`),view:t.view,onView:ie,openRequest:S}),t.connection===`elsewhere`&&(0,p.jsx)(aO,{onUseHere:a})]})}function fk(){let[e,t]=(0,l.useState)(`loading`);return(0,l.useEffect)(()=>{let e=!0,n=n=>e&&t(n);return(async()=>{try{if(!(await(await fetch(`/api/state`)).json()).hasOwner)return n(`setup`);let e=await(await fetch(`/api/session`,{cache:`no-store`})).json();n(e.signedIn===!0?`stage`:`login`)}catch{n(`login`)}})(),()=>{e=!1}},[]),e===`loading`?(0,p.jsx)(`div`,{className:`boot`,"aria-busy":`true`}):e===`setup`?(0,p.jsx)(g,{onDone:()=>t(`login`)}):e===`login`?(0,p.jsx)(h,{onLoggedIn:()=>t(`stage`)}):(0,p.jsx)(dk,{onSignedOut:()=>t(`login`)})}(0,u.createRoot)(document.getElementById(`root`)).render((0,p.jsx)(l.StrictMode,{children:(0,p.jsx)(fk,{})}));
|
|
4456
|
+
`)}async function dD(e,t){let n=t.fontEmbedCSS==null?t.skipFonts?null:await uD(e,t):t.fontEmbedCSS;if(n){let t=document.createElement(`style`),r=document.createTextNode(n);t.appendChild(r),e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}}async function fD(e,t={}){let{width:n,height:r}=nE(e,t),i=await zE(e,t,!0);return await dD(i,t),await $E(i,t),eD(i,t),await cE(i,n,r)}async function pD(e,t={}){let{width:n,height:r}=nE(e,t),i=await oE(await fD(e,t)),a=document.createElement(`canvas`),o=a.getContext(`2d`),s=t.pixelRatio||rE(),c=t.canvasWidth||n,l=t.canvasHeight||r;return a.width=c*s,a.height=l*s,t.skipAutoScale||aE(a),a.style.width=`${c}`,a.style.height=`${l}`,t.backgroundColor&&(o.fillStyle=t.backgroundColor,o.fillRect(0,0,a.width,a.height)),o.drawImage(i,0,0,a.width,a.height),a}var mD=1600,hD=.85;function gD(e,t){let n=Math.min(1,mD/Math.max(e,t,1));return{width:Math.max(1,Math.round(e*n)),height:Math.max(1,Math.round(t*n))}}async function _D(){let e=document.documentElement.getBoundingClientRect(),t=await pD(document.body,{width:Math.round(e.width),height:Math.round(e.height),pixelRatio:1,backgroundColor:`#050b10`,filter:e=>!(e instanceof HTMLElement&&e.dataset.noCapture!==void 0)}),n=gD(t.width,t.height),r=document.createElement(`canvas`);return r.width=n.width,r.height=n.height,r.getContext(`2d`).drawImage(t,0,0,n.width,n.height),new Promise((e,t)=>r.toBlob(n=>n?e(n):t(Error(`Could not encode the picture.`)),`image/jpeg`,hD))}var vD=class{opts;active=null;constructor(e){this.opts=e}async handle(e){if(e.type===`screen.cancel`){this.active&&this.active.id===e.id&&(this.active.cancelled=!0);return}if(this.active)return this.opts.send({type:`screen.denied`,id:e.id,reason:`busy`});let t={id:e.id,cancelled:!1};this.active=t;try{let n=await(this.opts.capture??_D)();if(t.cancelled)return;try{await this.opts.upload(e.id,n)}catch{this.opts.dispatch({type:`alert.add`,level:`warn`,text:`Could not send the picture of the screen to Friend.`})}}catch(n){t.cancelled||this.opts.send({type:`screen.denied`,id:e.id,reason:yD(n)})}finally{this.active===t&&(this.active=null)}}dispose(){this.active&&(this.active.cancelled=!0)}};function yD(e){return e?.name===`NotSupportedError`?`unsupported`:`failed`}var bD={401:`Please sign in again.`,413:`That recording was too long.`,409:`Friend is busy with the last request. Try again in a moment.`,429:`You're talking too fast. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function xD(e,t){let n;try{n=await fetch(`/api/voice/utterance`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e,signal:t})}catch(e){throw e.name===`AbortError`?e:Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||bD[n.status]||`The voice request failed (${n.status}).`)}let r=await n.json();return{text:typeof r.text==`string`?r.text:``}}var SD=0,CD=new Set;function wD(e){return CD.add(e),()=>CD.delete(e)}var TD=e=>CD.forEach(t=>{try{t(e)}catch{}}),ED=e=>/not compatible|audio capture|audiosession/i.test(String(e?.message??e));function DD(e){try{let t=navigator.audioSession;t&&t.type!==e&&(t.type=e)}catch{}}function OD(){SD===0&&DD(`playback`)}function kD(){SD++,SD===1&&TD(!0),DD(`play-and-record`);let e=!1;return()=>{e||(e=!0,SD=Math.max(0,SD-1),SD===0&&(DD(`playback`),TD(!1)))}}var AD=4096,jD=8,MD=20,ND=6e6;function PD(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}catch{return null}}var FD=class{ctx=null;analyser=null;pending=new Map;queue=[];current=null;busy=!1;gen=0;isPlaying=!1;unwatch=null;listeners=new Set;unlock(){OD();let e=this.ensureContext();e.state!==`running`&&e.resume().catch(()=>{})}locked(){return!this.ctx||this.ctx.state!==`running`}enqueue(e){if(!Number.isInteger(e.seq)||e.seq<0||e.seq>AD)return;let t=PD(e.data);if(!t)return;let n=this.pending.get(e.id);if(n||(this.pending.size>=jD&&this.pending.delete(this.pending.keys().next().value),n={parts:new Map,lastSeq:null,bytes:0},this.pending.set(e.id,n)),n.bytes+=t.length,n.bytes>ND){this.pending.delete(e.id);return}if(n.parts.set(e.seq,t),e.last&&(n.lastSeq=e.seq),n.lastSeq===null||n.parts.size!==n.lastSeq+1)return;this.pending.delete(e.id);let r=new Uint8Array([...n.parts.values()].reduce((e,t)=>e+t.length,0)),i=0;for(let e=0;e<=n.lastSeq;e++){let t=n.parts.get(e);if(!t)return;r.set(t,i),i+=t.length}for(this.queue.push(r.buffer);this.queue.length>MD;)this.queue.shift();this.pump()}stop(){this.gen++,this.queue=[],this.pending.clear(),this.busy=!1;let e=this.current;if(this.current=null,e){e.onended=null;try{e.stop()}catch{}}this.setPlaying(!1)}dispose(){this.stop(),this.ctx?.close().catch(()=>{}),this.unwatch?.(),this.unwatch=null,this.ctx=null,this.analyser=null}playing(){return this.isPlaying}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}level(){if(!this.analyser||!this.isPlaying)return 0;let e=new Uint8Array(this.analyser.fftSize);this.analyser.getByteTimeDomainData(e);let t=0;for(let n of e)t+=((n-128)/128)**2;return Math.min(1,Math.sqrt(t/e.length)*4)}ensureContext(){if(!this.ctx){let e=window.AudioContext??window.webkitAudioContext;this.ctx=new e,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=1024,this.analyser.connect(this.ctx.destination);let t=this.ctx;this.unwatch?.(),this.unwatch=wD(e=>{e&&t.state===`running`?t.suspend().catch(()=>{}):!e&&t.state!==`running`&&t.state!==`closed`&&t.resume().catch(()=>{})})}return this.ctx}setPlaying(e){this.isPlaying!==e&&(this.isPlaying=e,this.listeners.forEach(t=>t(e)))}async pump(){if(this.busy)return;let e=this.queue.shift();if(!e){this.setPlaying(!1);return}this.busy=!0;let t=this.gen;try{let n=this.ensureContext();if(n.state!==`running`){try{await n.resume()}catch{}if(t!==this.gen)return;if(n.state!==`running`){this.queue.unshift(e),this.busy=!1;return}}let r=await n.decodeAudioData(e);if(t!==this.gen)return;let i=n.createBufferSource();i.buffer=r,i.connect(this.analyser),i.onended=()=>{this.current===i&&(this.current=null,this.busy=!1,this.pump())},this.current=i,this.setPlaying(!0),i.start()}catch{if(t!==this.gen)return;this.busy=!1,this.pump()}}},ID=e=>new Promise(t=>setTimeout(t,e)),LD=[`audio/webm;codecs=opus`,`audio/webm`,`audio/mp4`,`audio/ogg;codecs=opus`],RD=3e3;function zD(e){let t=e;return t?.name===`NotAllowedError`||t?.name===`SecurityError`?Error(`Microphone permission was denied. Allow it in the browser to talk.`):t?.name===`NotFoundError`||t?.name===`OverconstrainedError`?Error(`No microphone was found.`):Error(t?.message||`Could not open the microphone.`)}var BD=class e{opts;stream=null;rec=null;chunks=[];ctx=null;analyser=null;timer=null;starting=!1;leaveSession=null;constructor(e={}){this.opts=e}static supported(){return typeof navigator<`u`&&!!navigator.mediaDevices?.getUserMedia&&typeof MediaRecorder<`u`}get active(){return this.rec!==null}async start(){if(!(this.rec||this.starting)){if(!e.supported())throw Error(`This browser cannot record audio here (use localhost or HTTPS).`);this.starting=!0;try{this.leaveSession=kD();try{let e=()=>navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0}});try{this.stream=await e()}catch(t){if(!ED(t))throw t;await ID(250),this.leaveSession?.(),this.leaveSession=kD(),this.stream=await e()}}catch(e){throw this.leaveSession?.(),this.leaveSession=null,zD(e)}try{let e=LD.find(e=>MediaRecorder.isTypeSupported(e));this.chunks=[];let t=new MediaRecorder(this.stream,e?{mimeType:e}:void 0);t.ondataavailable=e=>{e.data&&e.data.size>0&&this.chunks.push(e.data)},t.onerror=()=>this.failed();for(let e of this.stream.getTracks())e.onended=()=>this.failed();this.openMeter(this.stream),t.start(250),this.rec=t,this.opts.maxMs&&(this.timer=setTimeout(()=>{this.timer=null,this.opts.onLimit?.()},this.opts.maxMs))}catch(e){throw this.release(),zD(e)}}finally{this.starting=!1}}}stop(){let e=this.rec;return e?new Promise(t=>{let n=!1,r=null,i=()=>{if(n)return;n=!0,r&&clearTimeout(r);let i=new Blob(this.chunks,{type:e.mimeType||`audio/webm`});this.release(),t(i)};if(r=setTimeout(i,RD),e.onstop=i,e.state===`inactive`)return i();try{e.stop()}catch{i()}}):Promise.reject(Error(`Not recording.`))}cancel(){let e=this.rec;if(e){e.ondataavailable=null,e.onstop=null,e.onerror=null;try{e.state!==`inactive`&&e.stop()}catch{}}this.release()}level(){if(!this.analyser||!this.rec)return 0;let e=new Uint8Array(this.analyser.fftSize);this.analyser.getByteTimeDomainData(e);let t=0;for(let n of e)t+=((n-128)/128)**2;return Math.min(1,Math.sqrt(t/e.length)*4)}failed(){this.rec&&(this.cancel(),this.opts.onError?.())}openMeter(e){try{this.ctx=new AudioContext,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=1024,this.ctx.createMediaStreamSource(e).connect(this.analyser)}catch{this.analyser=null}}release(){this.timer&&clearTimeout(this.timer),this.timer=null,this.stream?.getTracks().forEach(e=>{e.onended=null,e.stop()}),this.ctx?.close().catch(()=>{}),this.stream=null,this.rec=null,this.ctx=null,this.analyser=null,this.chunks=[],this.leaveSession?.(),this.leaveSession=null}},VD=2e3,HD=()=>typeof window<`u`&&window.isSecureContext===!1,UD=50,WD=class{deps;recorder;player;mode=`idle`;pressed=!1;disposed=!1;uploads=0;toldAboutSound=!1;abort=null;poll=null;unsubscribe;constructor(e){this.deps=e;let t=()=>this.recorderFailed();this.recorder=e.recorder??e.makeRecorder?.(t)??new BD({maxMs:6e4,onLimit:()=>void this.pressEnd(),onError:t}),this.player=e.player??new FD,this.unsubscribe=this.player.onChange(e=>{this.mode!==`listening`&&this.mode!==`transcribing`&&this.setMode(e?`speaking`:`idle`)})}async pressStart(){if(!(this.pressed||this.disposed)){if(!this.deps.available()){this.alert(`warn`,`Voice is not available. Run: friend voice setup`);return}if(!(this.deps.supported?.()??BD.supported())){this.alert(`warn`,HD()?`This page is not secure, so the browser blocks the microphone. On the PC run: friend lan https on, restart Friend, and open the https:// address.`:`This browser cannot record audio here (use localhost or HTTPS).`);return}this.pressed=!0,this.player.unlock(),this.player.playing()&&(this.deps.send({type:`voice.interrupt`}),this.player.stop());try{await this.recorder.start()}catch(e){this.pressed=!1,this.alert(`error`,e.message),this.setMode(`idle`);return}if(!this.pressed){this.recorder.cancel(),this.setMode(`idle`);return}this.setMode(`listening`)}}async pressEnd(){if(!this.pressed||(this.pressed=!1,!this.recorder.active))return;let e=await this.recorder.stop();if(e.size<VD){this.alert(`info`,`Hold the key a little longer while you speak.`),this.setMode(`idle`);return}this.setMode(`transcribing`);let t=new AbortController;this.abort=t,this.uploads++;try{let{text:n}=await this.deps.post(e,t.signal);n.trim()||this.alert(`info`,`I didn't catch that.`)}catch(e){e.name!==`AbortError`&&this.alert(`error`,e.message)}finally{this.uploads--,this.abort===t&&(this.abort=null),this.settle()}}blur(){this.pressed&&(this.pressed=!1,this.recorder.cancel(),this.setMode(`idle`))}handleServer(e){if(e.type!==`audio.chunk`)return this.player.stop();this.player.enqueue(e),!this.toldAboutSound&&this.player.locked?.()&&(this.toldAboutSound=!0,this.deps.dispatch({type:`alert.add`,level:`info`,text:`Sound is blocked by the browser. Click or press a key once anywhere on the page to hear me.`}))}unlock(){this.player.unlock()}dispose(){this.disposed=!0,this.pressed=!1,this.stopPolling(),this.abort?.abort(),this.recorder.cancel(),this.player.stop(),this.player.dispose?.(),this.unsubscribe()}recorderFailed(){this.pressed=!1,this.recorder.cancel(),this.alert(`error`,`The microphone stopped working.`),this.setMode(`idle`)}settle(){this.uploads>0||this.mode!==`transcribing`||this.setMode(this.player.playing()?`speaking`:`idle`)}setMode(e){this.disposed||(this.mode=e,this.deps.dispatch({type:`voice.mode`,mode:e}),e===`listening`||e===`speaking`?this.startPolling():this.stopPolling())}startPolling(){this.stopPolling(),this.poll=setInterval(()=>{let e=this.mode===`listening`?this.recorder.level():this.player.level();this.deps.dispatch({type:`voice.level`,level:e})},UD)}stopPolling(){this.poll&&clearInterval(this.poll),this.poll=null}alert(e,t){this.disposed||this.deps.dispatch({type:`alert.add`,level:e,text:t})}};function GD(e){let[t,n]=(0,l.useReducer)(zT,NT),r=(0,l.useRef)(null),i=(0,l.useRef)(null),a=(0,l.useRef)(null),o=(0,l.useRef)(e);o.current=e;let s=(0,l.useRef)(t);return s.current=t,(0,l.useEffect)(()=>{let e=MT();r.current=e;let t=new WD({send:t=>e.send(t),dispatch:e=>n(e),post:xD,available:()=>s.current.voice.available});i.current=t;let c=new qT({send:t=>e.send(t),dispatch:e=>n(e),enabled:()=>s.current.camera.enabled,upload:async(e,t)=>{let n=await fetch(`/api/camera/frame/${encodeURIComponent(e)}`,{method:`POST`,headers:{"content-type":`image/jpeg`},body:t});if(!n.ok)throw Error(`upload failed (${n.status})`)}});a.current=c;let l=new vD({send:t=>e.send(t),dispatch:e=>n(e),upload:async(e,t)=>{let n=await fetch(`/api/screen/frame/${encodeURIComponent(e)}`,{method:`POST`,headers:{"content-type":`image/jpeg`},body:t});if(!n.ok)throw Error(`upload failed (${n.status})`)}}),u=e.onMessage(e=>{n(e);let r=e?.type,i=e?.id;(r===`camera.request`||r===`camera.cancel`)&&typeof i==`string`&&c.handle({type:r,id:i}),(r===`screen.request`||r===`screen.cancel`)&&typeof i==`string`&&l.handle({type:r,id:i}),(r===`audio.chunk`||r===`audio.stop`)&&t.handleServer(e)}),d=e.onState(e=>{n({type:`conn`,value:e}),e===`unauthorized`&&o.current(),e===`elsewhere`&&(t.blur(),c.dispose(),l.dispose())});return()=>{u(),d(),t.dispose(),c.dispose(),l.dispose(),e.close(),i.current=null,a.current=null,r.current=null}},[]),(0,l.useEffect)(()=>{t.camera.enabled||a.current?.dispose()},[t.camera.enabled]),{state:t,send:(0,l.useCallback)(e=>r.current?.send(e),[]),dispatch:(0,l.useCallback)(e=>n(e),[]),voice:(0,l.useMemo)(()=>({pressStart:()=>void i.current?.pressStart(),pressEnd:()=>void i.current?.pressEnd(),blur:()=>i.current?.blur(),unlock:()=>i.current?.unlock()}),[]),useHere:(0,l.useCallback)(()=>r.current?.takeOver(),[])}}var KD={401:`Please sign in again.`,403:`Incorrect PIN.`,413:`That recording was too long.`,429:`Too many attempts. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function qD(e,t){let n;try{n=await fetch(e,t)}catch{throw Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||KD[n.status]||`The request failed (${n.status}).`)}return await n.json()}var JD=(e,t)=>({method:e,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),YD={state:()=>qD(`/api/voice/enroll`,{}),sample:e=>qD(`/api/voice/enroll/sample`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e}),finish:e=>qD(`/api/voice/enroll/finish`,JD(`POST`,{pin:e})),cancel:async()=>{await qD(`/api/voice/enroll/cancel`,JD(`POST`,{}))},remove:async e=>{await qD(`/api/voice/enroll`,JD(`DELETE`,{pin:e}))}},XD=[`Friend, good evening. It is a pleasant day to get things done.`,`Open my projects and show me what changed today.`,`My voice is my key, so please remember it well.`,`Check the weather and read me the latest headlines.`,`Always protect the boss, and never trust a stranger.`],ZD=15e3;function QD({api:e=YD,createRecorder:t=e=>new BD(e),onClose:n,who:r}){let[i,a]=(0,l.useState)(null),[o,s]=(0,l.useState)(0),[c,u]=(0,l.useState)(null),[f,m]=(0,l.useState)(`record`),[h,g]=(0,l.useState)(!1),[_,v]=(0,l.useState)(!1),[y,b]=(0,l.useState)(null),[S,C]=(0,l.useState)(``),w=(0,l.useRef)(!0),T=(0,l.useRef)(null);(0,l.useEffect)(()=>(w.current=!0,e.state().then(e=>{w.current&&(a(e),s(e.samples))}).catch(e=>w.current&&b(e.message)),()=>{w.current=!1,T.current?.cancel(),T.current=null}),[e]);let E=(0,l.useCallback)(async()=>{let t=T.current;if(t){T.current=null,g(!1),v(!0);try{let n=await t.stop(),r=await e.sample(n);if(!w.current)return;s(r.count),u(r.note)}catch(e){w.current&&b(e.message)}finally{w.current&&v(!1)}}},[e]),D=async()=>{b(null),u(null);let e=t({maxMs:ZD,onLimit:()=>void E(),onError:()=>{T.current=null,w.current&&(g(!1),b(`The microphone stopped working. Try again.`))}});try{await e.start()}catch(e){w.current&&b(e.message);return}if(!w.current)return e.cancel();T.current=e,g(!0)},O=async e=>{b(null),v(!0);try{await e()}catch(e){w.current&&b(e.message)}finally{w.current&&(v(!1),C(``))}},k=async()=>{T.current?.cancel(),T.current=null,await e.cancel().catch(()=>{}),n()},A=i?.min??3,j=o%XD.length,ee=o<XD.length?`Phrase ${o+1} of ${XD.length}`:`Extra recording (${o} so far)`;return(0,p.jsxs)(`div`,{className:`approval enroll glass`,role:`dialog`,"aria-label":`Voice enrollment`,style:{pointerEvents:`auto`},children:[(0,p.jsx)(`div`,{className:`approval-head`,children:(0,p.jsx)(`span`,{className:`approval-title`,children:r?`Teach Friend ${r}'s voice`:`Teach Friend your voice`})}),f===`record`&&(0,p.jsxs)(p.Fragment,{children:[!r&&i?.enrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`Your voice is already saved. Saving a new one replaces it.`}),r&&(0,p.jsxs)(`p`,{className:`auth-note`,children:[`Hand the device to `,r,`. `,r,` reads each sentence aloud, close to the microphone, in a quiet room.`]}),(0,p.jsxs)(`p`,{className:`auth-note`,children:[ee,`. Press Record, read this aloud in a quiet room, then press Stop.`]}),(0,p.jsx)(`pre`,{className:`approval-summary`,"data-testid":`enroll-phrase`,style:{whiteSpace:`pre-wrap`},children:XD[j]}),(0,p.jsxs)(`div`,{role:`status`,className:`auth-note`,children:[o,` recorded`,o>=A?` — enough to save`:` — at least ${A} needed`,`.`,c?` ${c}`:``]}),y&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:y}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[h?(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,onClick:()=>void E(),children:`Stop`}):(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:_||!i||o>=(i?.max??8),onClick:()=>void D(),children:_?`Uploading…`:`Record`}),(0,p.jsx)(`button`,{type:`button`,style:d,disabled:h||_||o<A,onClick:()=>m(`pin-save`),children:r?`Save ${r}'s voice`:`Save my voice`}),!r&&i?.enrolled&&(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:h||_,onClick:()=>m(`pin-delete`),children:`Delete my voice`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>void k(),children:`Cancel`})]})]}),(f===`pin-save`||f===`pin-delete`)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:f===`pin-save`?r?`Enter your PIN to save ${r}'s voice.`:`Enter your PIN to save your voice.`:`Enter your PIN to delete your saved voice.`}),(0,p.jsx)(x,{pin:S,onChange:C,onSubmit:f===`pin-save`?()=>!_&&void O(async()=>{await e.finish(S),w.current&&m(`saved`)}):void 0}),y&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:y}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[f===`pin-save`?(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:_||S.length<6,onClick:()=>void O(async()=>{await e.finish(S),w.current&&m(`saved`)}),children:`Save`}):(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:_||S.length<6,onClick:()=>void O(async()=>{await e.remove(S),w.current&&m(`deleted`)}),children:`Delete`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>{C(``),b(null),m(`record`)},children:`Back`})]})]}),(f===`saved`||f===`deleted`)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:f===`saved`?r?`${r}'s voice is saved. From now on I will know when ${r} is talking.`:`Your voice is saved. From now on I will tell you apart from other speakers.`:`Your voice was deleted. Every voice is treated as yours until you enroll again.`}),(0,p.jsx)(`div`,{className:`approval-actions`,children:(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,onClick:n,children:`Done`})})]})]})}var $D=new Set([`INPUT`,`TEXTAREA`,`SELECT`,`BUTTON`,`A`,`SUMMARY`]),eO=new Set([`button`,`checkbox`,`switch`,`tab`,`menuitem`,`link`,`radio`,`option`,`textbox`,`combobox`,`slider`]),tO=e=>e instanceof HTMLElement&&($D.has(e.tagName)||e.isContentEditable||eO.has(e.getAttribute(`role`)??``)),nO=e=>e.code===`Space`||e.key===` `;function rO(e){let t=(0,l.useRef)(e);t.current=e,(0,l.useEffect)(()=>{let e=!1,n=n=>{!nO(n)||n.ctrlKey||n.metaKey||n.altKey||tO(n.target)||tO(document.activeElement)||(n.preventDefault(),!(n.repeat||e)&&(e=!0,t.current.pressStart()))},r=n=>{nO(n)&&e&&(e=!1,n.preventDefault(),t.current.pressEnd())},i=()=>{e=!1,t.current.blur()},a=()=>{document.hidden&&i()};return window.addEventListener(`keydown`,n),window.addEventListener(`keyup`,r),window.addEventListener(`blur`,i),document.addEventListener(`visibilitychange`,a),()=>{window.removeEventListener(`keydown`,n),window.removeEventListener(`keyup`,r),window.removeEventListener(`blur`,i),document.removeEventListener(`visibilitychange`,a)}},[])}function iO(e){let t=(0,l.useRef)(e);t.current=e,(0,l.useEffect)(()=>{let e=()=>t.current.unlock(),n=[`pointerdown`,`keydown`,`touchend`];for(let t of n)window.addEventListener(t,e,{passive:!0});return()=>{for(let t of n)window.removeEventListener(t,e)}},[])}function aO({onUseHere:e}){return(0,p.jsx)(`div`,{className:`elsewhere`,role:`alertdialog`,"aria-labelledby":`elsewhere-title`,"data-testid":`elsewhere`,children:(0,p.jsxs)(`div`,{className:`elsewhere-card`,children:[(0,p.jsx)(`h2`,{id:`elsewhere-title`,children:`Friend is open in another window`}),(0,p.jsx)(`p`,{children:`Friend works in one window at a time. Click “Use here” to use it in this window instead; the other one will stop.`}),(0,p.jsx)(`button`,{type:`button`,className:`elsewhere-btn`,onClick:e,autoFocus:!0,children:`Use here`})]})})}function oO(e,t,n){let r=Math.max(100,Math.round(e)),i=Math.max(100,Math.round(t));return{width:r,height:i,kind:r<=599?`phone`:n||r<1024?`tablet`:`desktop`,orientation:i>r?`portrait`:`landscape`,touch:n}}var sO=()=>typeof matchMedia==`function`&&matchMedia(`(pointer: coarse)`).matches;function cO(){return oO(window.innerWidth,window.innerHeight,sO())}var lO=(e,t)=>!!e&&e.width===t.width&&e.height===t.height&&e.kind===t.kind&&e.orientation===t.orientation&&e.touch===t.touch;function uO(e,t){let n=(0,l.useRef)(null),r=(0,l.useRef)(e);r.current=e,(0,l.useEffect)(()=>{if(t!==`open`){n.current=null;return}let e=()=>{let e=cO();lO(n.current,e)||(n.current=e,r.current({type:`ui.screen`,...e}))};e();let i=null,a=()=>{i&&clearTimeout(i),i=setTimeout(e,400)};return window.addEventListener(`resize`,a),window.addEventListener(`orientationchange`,a),()=>{i&&clearTimeout(i),window.removeEventListener(`resize`,a),window.removeEventListener(`orientationchange`,a)}},[t])}var dO={401:`Please sign in again.`,403:`Incorrect PIN.`,413:`That recording was too long.`,429:`Too many attempts. Wait a moment.`,503:`Voice is not available. Run: friend voice setup`};async function fO(e,t={}){let n;try{n=await fetch(e,t)}catch{throw Error(`Could not reach Friend. Check the connection.`)}if(!n.ok){let e=``;try{e=(await n.json()).error??``}catch{}throw Error(e||dO[n.status]||`The request failed (${n.status}).`)}return await n.json()}var pO=(e,t)=>({method:e,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),mO={overview:()=>fO(`/api/voice/people`),begin:e=>fO(`/api/voice/people/begin`,pO(`POST`,{name:e})),recording:{state:async()=>(await fO(`/api/voice/people`)).enrolling??{enrolled:!1,samples:0,min:3,max:8},sample:e=>fO(`/api/voice/people/sample`,{method:`POST`,headers:{"content-type":e.type||`audio/webm`},body:e}),finish:e=>fO(`/api/voice/people/finish`,pO(`POST`,{pin:e})),cancel:async()=>{await fO(`/api/voice/people/cancel`,pO(`POST`,{}))},remove:async()=>{}},removePerson:async(e,t)=>{await fO(`/api/voice/people/${e}`,pO(`DELETE`,{pin:t}))}};function hO({api:e=mO,createRecorder:t,onClose:n}){let[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)({kind:`list`}),[s,c]=(0,l.useState)(``),[u,f]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(null),v=(0,l.useRef)(!0),y=(0,l.useCallback)(()=>{e.overview().then(e=>v.current&&i(e)).catch(e=>v.current&&_(e.message))},[e]);(0,l.useEffect)(()=>(v.current=!0,y(),()=>{v.current=!1}),[y]);let b=async()=>{_(null),h(!0);try{let t=await e.begin(s.trim());v.current&&o({kind:`record`,name:t.name})}catch(e){v.current&&_(e.message)}finally{v.current&&h(!1)}},S=async t=>{_(null),h(!0);try{if(await e.removePerson(t.id,u),!v.current)return;o({kind:`list`}),y()}catch(e){v.current&&_(e.message)}finally{v.current&&(h(!1),f(``))}};return a.kind===`record`?(0,p.jsx)(QD,{api:e.recording,who:a.name,...t?{createRecorder:t}:{},onClose:()=>{c(``),o({kind:`list`}),y()}}):(0,p.jsxs)(`div`,{className:`approval enroll glass`,role:`dialog`,"aria-label":`Family voices`,style:{pointerEvents:`auto`},children:[(0,p.jsx)(`div`,{className:`approval-head`,children:(0,p.jsx)(`span`,{className:`approval-title`,children:`Family voices`})}),a.kind===`list`&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`p`,{className:`auth-note`,children:`Friend knows your voice. Add the people at home, so it knows who is talking and answers them by name. They can chat and ask for the weather, but cannot use your PC or see your private things.`}),r&&!r.ownerEnrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`First teach Friend your own voice (Esc, then Enroll my voice).`}),r&&r.people.length===0&&r.ownerEnrolled&&(0,p.jsx)(`p`,{className:`auth-note`,children:`Nobody added yet.`}),r&&r.people.length>0&&(0,p.jsx)(`ul`,{className:`household-list`,"aria-label":`People Friend knows`,children:r.people.map(e=>(0,p.jsxs)(`li`,{className:`household-row`,children:[(0,p.jsx)(`span`,{children:e.name}),(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,onClick:()=>o({kind:`remove`,person:e}),"aria-label":`Remove ${e.name}`,children:`Remove`})]},e.id))}),r&&r.ownerEnrolled&&r.people.length<r.max&&(0,p.jsxs)(`label`,{className:`settings-field`,children:[(0,p.jsx)(`span`,{children:`Add a person`}),(0,p.jsx)(`input`,{value:s,maxLength:40,placeholder:`Name, for example Priya`,onChange:e=>c(e.target.value),onKeyDown:e=>e.key===`Enter`&&s.trim()&&!m&&void b()})]}),g&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:g}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[r&&r.ownerEnrolled&&r.people.length<r.max&&(0,p.jsx)(`button`,{type:`button`,style:d,className:`primary`,disabled:m||!s.trim(),onClick:()=>void b(),children:`Record their voice`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:n,children:`Close`})]})]}),a.kind===`remove`&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`auth-note`,children:[`Enter your PIN to remove `,a.person.name,`’s voice. Friend will treat their voice as a stranger’s.`]}),(0,p.jsx)(x,{pin:u,onChange:f}),g&&(0,p.jsx)(`p`,{role:`alert`,className:`auth-error`,children:g}),(0,p.jsxs)(`div`,{className:`approval-actions`,children:[(0,p.jsx)(`button`,{type:`button`,style:d,className:`danger`,disabled:m||u.length<6,onClick:()=>void S(a.person),children:`Remove`}),(0,p.jsx)(`button`,{type:`button`,style:d,onClick:()=>{f(``),_(null),o({kind:`list`})},children:`Back`})]})]})]})}var gO=`▌▍▎▏█▓▒░<>/\\|+-=*#%&0123456789ABCDEF`;function _O(e,t,n=Math.random){let r=[...e];if(t>=1)return e;let i=Math.floor(r.length*Math.max(0,t));return r.map((e,t)=>t<i||e===` `?e:gO[Math.floor(n()*36)]).join(``)}var vO=e=>e.length===0?0:Math.min(24,Math.max(6,Math.ceil([...e].length/2)));function yO(e,t){let[n,r]=(0,l.useState)(e),i=(0,l.useRef)(e);return(0,l.useEffect)(()=>{if(!t||e===i.current){i.current=e,r(e);return}i.current=e;let n=vO(e);if(n===0){r(e);return}let a=0,o=setInterval(()=>{a++,r(_O(e,a/n)),a>=n&&clearInterval(o)},320/n);return()=>clearInterval(o)},[e,t]),n}function bO(e){let t=e.currentTarget,n=t.getBoundingClientRect(),r=document.createElement(`span`);r.className=`hud-ripple`;let i=Math.max(n.width,n.height)*2;r.style.width=r.style.height=`${i}px`,r.style.left=`${e.clientX-n.left-i/2}px`,r.style.top=`${e.clientY-n.top-i/2}px`,t.appendChild(r),r.addEventListener(`animationend`,()=>r.remove(),{once:!0}),setTimeout(()=>r.remove(),900)}function xO({items:e,animations:t,onAction:n}){let[r,i]=(0,l.useState)(null),a=(0,l.useRef)(void 0);if((0,l.useEffect)(()=>()=>clearTimeout(a.current),[]),e.length===0)return null;let o=e=>{t!==`off`&&(i(e.id),clearTimeout(a.current),a.current=setTimeout(()=>i(null),650)),n(e)};return(0,p.jsxs)(B,{id:`launcher`,label:`Quick launch`,wholeBox:!0,testId:`launcher`,className:`hud hud-launcher${t===`full`?` hud-boot`:``}`,children:[(0,p.jsx)(`div`,{className:`hud-kicker`,children:`Quick launch`}),(0,p.jsx)(`ul`,{className:`hud-stack`,children:e.map((e,n)=>(0,p.jsx)(`li`,{className:`hud-tab hud-cut${r===e.id?` engaged`:``}${t===`full`?` hud-boot`:``}`,style:{"--i":n+1},children:(0,p.jsxs)(`button`,{type:`button`,className:`hud-tab-main`,"aria-label":e.label,onPointerDown:t===`off`?void 0:bO,onClick:()=>o(e),children:[(0,p.jsx)(`span`,{className:`hud-icon`,"aria-hidden":`true`,children:e.icon}),(0,p.jsx)(`span`,{className:`hud-tab-label`,children:e.label}),(0,p.jsx)(`span`,{className:`hud-tab-engaged`,"aria-hidden":`true`,children:`ENGAGED`}),(0,p.jsx)(`span`,{className:`hud-sweep`,"aria-hidden":`true`}),(0,p.jsx)(`span`,{className:`hud-scan`,"aria-hidden":`true`})]})},e.id))})]})}var SO=(e,t=18)=>(0,p.jsx)(`svg`,{width:t,height:t,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.8`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:e}),CO=()=>SO((0,p.jsx)(`path`,{d:`M7 4.5v15l12-7.5z`,fill:`currentColor`})),wO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`rect`,{x:`6`,y:`4.5`,width:`4`,height:`15`,fill:`currentColor`}),(0,p.jsx)(`rect`,{x:`14`,y:`4.5`,width:`4`,height:`15`,fill:`currentColor`})]})),TO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M5 5v14l10-7z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M18 5v14`})]})),EO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M19 5v14L9 12z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M6 5v14`})]})),DO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M3 7h3.5c3 0 4 2 5.5 5s2.500 5 5.500 5H21`}),(0,p.jsx)(`path`,{d:`M3 17h3.5c1.500 0 2.500-.6 3.400-1.800M13.500 8.800C14.500 7.600 15.500 7 17 7h4`}),(0,p.jsx)(`path`,{d:`m18.500 4.500 2.500 2.500-2.500 2.500M18.500 14.500l2.500 2.500-2.500 2.500`})]})),OO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M17 3l3 3-3 3`}),(0,p.jsx)(`path`,{d:`M4 11V9a3 3 0 0 1 3-3h13M7 21l-3-3 3-3`}),(0,p.jsx)(`path`,{d:`M20 13v2a3 3 0 0 1-3 3H4`})]})),kO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M4 9.500v5h3.500L12 18.500v-13L7.500 9.500z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`M15.500 9a4 4 0 0 1 0 6M18 6.500a7.500 7.500 0 0 1 0 11`})]})),AO=()=>SO((0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`path`,{d:`M4 9.500v5h3.500L12 18.500v-13L7.500 9.500z`,fill:`currentColor`}),(0,p.jsx)(`path`,{d:`m16 9 5 6M21 9l-5 6`})]})),jO=()=>SO((0,p.jsx)(`path`,{d:`M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5`})),MO=()=>SO((0,p.jsx)(`path`,{d:`M9 4v5H4M15 4v5h5M9 20v-5H4M15 20v-5h5`})),NO=()=>SO((0,p.jsx)(`path`,{d:`M6 6l12 12M18 6 6 18`})),PO=()=>SO((0,p.jsx)(`path`,{d:`M9 18V6l10-2v12`}),22),FO=56,IO=()=>({bars:new Float32Array(FO),bass:0,left:0,right:0});function LO(e,t,n,r,i){let a=n?.82:.9;if(t&&n){t.getByteFrequencyData(i);let n=Math.min(i.length,96);for(let t=0;t<FO;t++){let r=Math.min(n-1,Math.floor((t/FO)**1.6*n));e.bars[t]=Math.max((i[r]??0)/255,e.bars[t]*a)}}else if(n)for(let t=0;t<FO;t++)e.bars[t]=Math.max(.12+.28*Math.abs(Math.sin(r/420+t*.55)*Math.cos(r/900+t*.21)),e.bars[t]*a);else for(let t=0;t<FO;t++)e.bars[t]=e.bars[t]*a;let o=0;for(let t=0;t<6;t++)o+=e.bars[t];e.bass=Math.min(1,o/6*1.15);let s=0,c=0;for(let t=0;t<FO/2;t++)s+=e.bars[t],c+=e.bars[t+FO/2];e.left=Math.min(1,s/(FO/2)*1.6),e.right=Math.min(1,c/(FO/2)*3.2)}function RO({progress:e,playing:t,cover:n,analyser:r,levels:i,visualizer:a,animate:o,size:s}){let c=(0,l.useRef)(null),u=(0,l.useRef)(null),d=(0,l.useRef)(new Uint8Array(new ArrayBuffer(128)));(0,l.useEffect)(()=>{let e=c.current,n=e?.getContext(`2d`);if(!e||!n||!o)return;let l=0,f=Math.min(2,window.devicePixelRatio||1);e.width=e.height=Math.round(s*f);let p=getComputedStyle(e).getPropertyValue(`--accent`).trim()||`#3fd8ff`,m=e=>{if(LO(i,r,t,e,d.current),u.current?.style.setProperty(`--bass`,i.bass.toFixed(3)),n.setTransform(f,0,0,f,0,0),n.clearRect(0,0,s,s),a){let e=s/2,t=s*.335,r=s*.135;n.lineCap=`round`,n.lineWidth=Math.max(1.5,s/90);for(let a=0;a<FO;a++){let o=a/FO*Math.PI*2-Math.PI/2,s=i.bars[a],c=2+s*r;n.strokeStyle=p,n.globalAlpha=.35+s*.65,n.beginPath(),n.moveTo(e+Math.cos(o)*t,e+Math.sin(o)*t),n.lineTo(e+Math.cos(o)*(t+c),e+Math.sin(o)*(t+c)),n.stroke()}n.globalAlpha=1}(t||!i.bars.every(e=>e<.01)||a)&&(l=requestAnimationFrame(m))};return l=requestAnimationFrame(m),()=>cancelAnimationFrame(l)},[r,t,a,o,s,i]);let f=Math.max(0,Math.min(1,e))*100;return(0,p.jsxs)(`div`,{ref:u,className:`hud-dial${t?` playing`:``}`,style:{width:s,height:s},role:`img`,"aria-label":`Playback dial`,children:[(0,p.jsxs)(`svg`,{className:`hud-dial-svg`,viewBox:`0 0 200 200`,"aria-hidden":`true`,children:[(0,p.jsx)(`circle`,{className:`hud-dial-ticks`,cx:`100`,cy:`100`,r:`96`}),(0,p.jsx)(`circle`,{className:`hud-dial-track`,cx:`100`,cy:`100`,r:`88`}),(0,p.jsx)(`circle`,{className:`hud-dial-arc`,cx:`100`,cy:`100`,r:`88`,pathLength:`100`,strokeDasharray:`${f} 100`,transform:`rotate(-90 100 100)`}),(0,p.jsx)(`circle`,{className:`hud-dial-inner`,cx:`100`,cy:`100`,r:`62`}),(0,p.jsxs)(`g`,{className:`hud-needle`,children:[(0,p.jsx)(`line`,{x1:`100`,y1:`100`,x2:`100`,y2:`14`}),(0,p.jsx)(`circle`,{cx:`100`,cy:`14`,r:`2.500`})]})]}),(0,p.jsx)(`canvas`,{ref:c,className:`hud-spectrum`,style:{width:s,height:s},"aria-hidden":`true`}),(0,p.jsx)(`div`,{className:`hud-cover`,style:n?{backgroundImage:`url("${n}")`}:void 0,children:!n&&(0,p.jsx)(PO,{})})]})}var zO=e=>{let t=Math.max(0,Math.floor(Number.isFinite(e)?e:0));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`},BO=new Map;function VO(e){let[t,n]=(0,l.useState)(e?BO.get(e)??!1:!1);return(0,l.useEffect)(()=>{if(!e)return n(!1);if(BO.has(e))return n(BO.get(e));let t=!0,r=new Image;return r.onload=()=>{BO.set(e,!0),t&&n(!0)},r.onerror=()=>{BO.set(e,!1),t&&n(!1)},r.src=`/api/music/cover/${e}`,()=>{t=!1}},[e]),e&&t?`/api/music/cover/${e}`:null}async function HO(e,t){let n=await fetch(`/api/music/library?q=${encodeURIComponent(e)}&limit=${t}`);return n.ok?await n.json():{tracks:[],total:0}}var UO=e=>({id:e.id,title:e.title,artist:e.artist,album:e.album,durationSec:e.durationSec});function WO({levels:e,animate:t,side:n}){let r=(0,l.useRef)(null);return(0,l.useEffect)(()=>{if(!t)return;let i=0,a=r.current,o=()=>{if(a){let t=n===`left`?e.left:e.right,r=Math.round(t*12);a.querySelectorAll(`i`).forEach((e,t)=>e.classList.toggle(`on`,t<r))}i=requestAnimationFrame(o)};return i=requestAnimationFrame(o),()=>cancelAnimationFrame(i)},[e,t,n]),(0,p.jsx)(`div`,{ref:r,className:`hud-levels ${n}`,"aria-hidden":`true`,children:Array.from({length:12},(e,t)=>(0,p.jsx)(`i`,{},t))})}function GO({player:e,anim:t}){let{state:n,dispatch:r}=e,i=(0,l.useCallback)(async()=>{if(n.queue.length>0)return r({type:`resume`});let e=await HO(``,500);r({type:`play`,tracks:e.tracks.map(UO),mode:`replace`,...n.shuffle?{shuffle:!0}:{}})},[n.queue.length,n.shuffle,r]),a=e=>n=>{t!==`off`&&bO(n),e()};return(0,p.jsxs)(`div`,{className:`hud-controls`,role:`group`,"aria-label":`Player controls`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Shuffle`,"aria-pressed":n.shuffle,title:`Shuffle`,onClick:()=>r({type:`shuffle`}),children:(0,p.jsx)(DO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Previous track`,title:`Previous`,onPointerDown:a(()=>{}),onClick:()=>r({type:`previous`}),children:(0,p.jsx)(EO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn hud-btn-main`,"aria-label":n.playing?`Pause`:`Play`,title:n.playing?`Pause`:`Play`,onPointerDown:a(()=>{}),onClick:()=>n.playing?r({type:`pause`}):void i(),children:n.playing?(0,p.jsx)(wO,{}):(0,p.jsx)(CO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Next track`,title:`Next`,onPointerDown:a(()=>{}),onClick:()=>r({type:`next`}),children:(0,p.jsx)(TO,{})}),(0,p.jsxs)(`button`,{type:`button`,className:`hud-btn${n.repeat===`off`?``:` on`}`,"aria-label":`Repeat: ${n.repeat}`,title:`Repeat: ${n.repeat}`,onClick:()=>r({type:`repeat`,mode:n.repeat===`off`?`all`:n.repeat===`all`?`one`:`off`}),children:[(0,p.jsx)(OO,{}),n.repeat===`one`&&(0,p.jsx)(`sup`,{children:`1`})]})]})}function KO({player:e}){let{state:t,dispatch:n}=e,r=t.duration>0?t.position/t.duration*100:0;return(0,p.jsxs)(`div`,{className:`hud-timeline`,children:[(0,p.jsx)(`span`,{className:`hud-time`,children:zO(t.position)}),(0,p.jsx)(`input`,{type:`range`,className:`hud-range`,"aria-label":`Position`,min:0,max:Math.max(1,Math.floor(t.duration)),step:1,value:Math.min(Math.floor(t.position),Math.max(1,Math.floor(t.duration))),style:{"--fill":`${r}%`},disabled:t.duration<=0,onChange:e=>n({type:`seek`,seconds:Number(e.target.value)})}),(0,p.jsxs)(`span`,{className:`hud-time`,children:[`-`,zO(Math.max(0,t.duration-t.position))]})]})}function qO({player:e}){let{state:t,dispatch:n}=e;return(0,p.jsxs)(`div`,{className:`hud-volume`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":t.muted?`Unmute`:`Mute`,onClick:()=>n({type:`mute`}),children:t.muted||t.volume===0?(0,p.jsx)(AO,{}):(0,p.jsx)(kO,{})}),(0,p.jsx)(`input`,{type:`range`,className:`hud-range`,"aria-label":`Volume`,min:0,max:100,value:t.muted?0:t.volume,style:{"--fill":`${t.muted?0:t.volume}%`},onChange:e=>n({type:`volume`,level:Number(e.target.value)})})]})}function JO({player:e,anim:t}){let{state:n,dispatch:r}=e,[i,a]=(0,l.useState)(n.queue.length?`queue`:`library`),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(null);(0,l.useEffect)(()=>{if(i!==`library`)return;let e=!0,t=setTimeout(()=>void HO(o,100).then(t=>e&&u(t)),o?250:0);return()=>{e=!1,clearTimeout(t)}},[i,o]);let d=i===`queue`?n.queue.map((e,t)=>({track:e,index:t})):(c?.tracks??[]).map((e,t)=>({track:UO(e),index:t}));return(0,p.jsxs)(`div`,{className:`hud-playlist`,children:[(0,p.jsxs)(`div`,{className:`hud-tabs`,role:`tablist`,children:[[`queue`,`library`].map(e=>(0,p.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":i===e,className:`hud-chip${i===e?` on`:``}`,onClick:()=>a(e),children:e===`queue`?`Queue (${n.queue.length})`:`Library`},e)),i===`queue`&&n.queue.length>0&&(0,p.jsx)(`button`,{type:`button`,className:`hud-chip`,onClick:()=>r({type:`clear`}),children:`Clear`})]}),i===`library`&&(0,p.jsx)(`input`,{className:`hud-search`,type:`search`,placeholder:`Search title, artist or album`,"aria-label":`Search the music`,value:o,onChange:e=>s(e.target.value)}),(0,p.jsxs)(`ul`,{className:`hud-list`,children:[d.length===0&&(0,p.jsx)(`li`,{className:`hud-empty`,children:i===`queue`?`The queue is empty.`:c?`No music matches.`:`Loading…`}),d.map(({track:e,index:a},o)=>{let s=i===`queue`&&a===n.index;return(0,p.jsxs)(`li`,{className:`hud-tab hud-cut${s?` current`:``}${t===`full`?` hud-boot`:``}`,style:{"--i":Math.min(o,12)},children:[(0,p.jsxs)(`button`,{type:`button`,className:`hud-tab-main`,"aria-current":s?`true`:void 0,onPointerDown:t===`off`?void 0:bO,onClick:()=>r(i===`queue`?{type:`jump`,index:a}:{type:`play`,tracks:(c?.tracks??[]).map(UO),mode:`replace`,start:a}),children:[(0,p.jsx)(`span`,{className:`hud-tab-title`,children:e.title}),(0,p.jsx)(`small`,{children:e.artist||e.album})]}),i===`library`&&(0,p.jsx)(`button`,{type:`button`,className:`hud-mini`,"aria-label":`Add ${e.title} to the queue`,title:`Add to the queue`,onClick:()=>r({type:`play`,tracks:[e],mode:`add`}),children:`+`}),i===`queue`&&(0,p.jsx)(`button`,{type:`button`,className:`hud-mini`,"aria-label":`Remove ${e.title} from the queue`,title:`Remove`,onClick:()=>r({type:`remove`,index:a}),children:`×`})]},`${e.id}-${a}`)})]})]})}function YO({player:e,music:t,animations:n}){let{state:r,dispatch:i,current:a,blocked:o,analyser:s,unlock:c}=e,u=(0,l.useMemo)(IO,[]),d=VO(a?.id),f=r.view===`full`,m=yO(a?.title??``,n===`full`);if(!t?.folderSet||r.view===`hidden`)return null;let h=r.duration>0?r.position/r.duration:0,g=n!==`off`;return(0,p.jsxs)(B,{id:`music`,label:`Music player`,wholeBox:!0,testId:`music`,className:`hud hud-music hud-cut ${f?`full`:`mini`}${r.playing?` playing`:``}${n===`full`?` hud-boot`:``}`,children:[(0,p.jsxs)(`header`,{className:`hud-music-head`,children:[(0,p.jsx)(`span`,{className:`hud-kicker`,children:`Media player`}),(0,p.jsxs)(`span`,{className:`hud-head-actions`,children:[(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":f?`Smaller player`:`Bigger player`,title:f?`Smaller`:`Bigger`,onClick:()=>i({type:`view`,view:f?`mini`:`full`}),children:f?(0,p.jsx)(MO,{}):(0,p.jsx)(jO,{})}),(0,p.jsx)(`button`,{type:`button`,className:`hud-btn`,"aria-label":`Hide the player`,title:`Hide (the music keeps playing)`,onClick:()=>i({type:`view`,view:`hidden`}),children:(0,p.jsx)(NO,{})})]})]}),(0,p.jsxs)(`div`,{className:`hud-music-body`,children:[(0,p.jsxs)(`div`,{className:`hud-music-left`,children:[f&&(0,p.jsx)(WO,{levels:u,animate:g,side:`left`}),(0,p.jsx)(RO,{progress:h,playing:r.playing,cover:d,analyser:s,levels:u,visualizer:t.visualizer,animate:g,size:f?250:112}),f&&(0,p.jsx)(WO,{levels:u,animate:g,side:`right`})]}),(0,p.jsxs)(`div`,{className:`hud-music-main`,children:[(0,p.jsxs)(`div`,{className:`hud-now`,"aria-live":`polite`,children:[(0,p.jsx)(`b`,{className:`hud-title`,children:a?m:`Nothing playing`}),(0,p.jsx)(`small`,{className:`hud-sub`,children:a?[a.artist,a.album].filter(Boolean).join(` — `):`Press play, or ask for some music.`})]}),(0,p.jsx)(KO,{player:e}),(0,p.jsx)(GO,{player:e,anim:n}),f&&(0,p.jsx)(qO,{player:e}),o&&(0,p.jsx)(`button`,{type:`button`,className:`hud-unlock`,onClick:c,children:`Tap to enable sound`})]}),f&&(0,p.jsx)(JO,{player:e,anim:n})]})]})}var XO=2e3,ZO=3,QO=e=>({queue:[],index:-1,playing:!1,position:0,duration:0,volume:e.volume,muted:!1,shuffle:e.shuffle,repeat:e.repeat,view:e.view});function $O(e,t=Math.random){let n=[...e];for(let e=n.length-1;e>0;e--){let r=Math.floor(t()*(e+1));[n[e],n[r]]=[n[r],n[e]]}return n}var ek=(e,t,n)=>Math.min(n,Math.max(t,e)),tk=(e,t,n)=>({...e,index:t,playing:n,position:0,duration:0});function nk(e,t,n={}){let r=n.shuffle??$O,i=e.queue.length-1;switch(t.type){case`play`:{if(t.tracks.length===0)return e;let n=t.tracks.slice(0,XO);if(t.mode===`replace`){let i=t.shuffle?r(n):n;return{...tk(e,t.shuffle?0:ek(t.start??0,0,i.length-1),!0),queue:i,shuffle:t.shuffle?!0:e.shuffle}}if(e.queue.length===0)return{...tk(e,0,!0),queue:n};let i=t.mode===`next`?e.index+1:e.queue.length;return{...e,queue:[...e.queue.slice(0,i),...n,...e.queue.slice(i)].slice(0,XO)}}case`next`:return i<0?e:e.index<i?tk(e,e.index+1,!0):e.repeat===`off`?{...e,playing:!1,position:0}:tk(e,0,!0);case`previous`:return i<0?e:e.position>ZO?{...e,position:0}:e.index>0?tk(e,e.index-1,e.playing||!0):e.repeat===`all`?tk(e,i,!0):{...e,position:0};case`ended`:return i<0?e:e.repeat===`one`?tk(e,e.index,!0):e.index<i?tk(e,e.index+1,!0):e.repeat===`all`?tk(e,0,!0):{...e,playing:!1,position:0};case`failed`:return i<0?e:e.index<i?tk(e,e.index+1,!0):{...e,playing:!1,position:0};case`pause`:return e.playing?{...e,playing:!1}:e;case`resume`:return e.index>=0&&!e.playing?{...e,playing:!0}:e;case`toggle`:return e.index<0?e:{...e,playing:!e.playing};case`stop`:return{...e,playing:!1,position:0};case`volume`:{let n=typeof t.level==`number`?Math.round(t.level):typeof t.delta==`number`?e.volume+Math.round(t.delta):e.volume;return{...e,volume:ek(n,0,100),muted:typeof t.level==`number`||(t.delta??0)>0?!1:e.muted}}case`mute`:return{...e,muted:t.on??!e.muted};case`seek`:{let n=typeof t.seconds==`number`?t.seconds:typeof t.percent==`number`?e.duration*ek(t.percent,0,100)/100:e.position;return{...e,position:ek(n,0,e.duration>0?e.duration:Math.max(n,0))}}case`repeat`:return{...e,repeat:t.mode};case`shuffle`:{if(!(t.on??!e.shuffle))return{...e,shuffle:!1};let n=e.queue.slice(0,e.index+1);return{...e,shuffle:!0,queue:[...n,...r(e.queue.slice(e.index+1))]}}case`view`:return{...e,view:t.view};case`remove`:{if(!Number.isInteger(t.index)||t.index<0||t.index>i)return e;let n=e.queue.filter((e,n)=>n!==t.index);return n.length===0?{...e,queue:n,index:-1,playing:!1,position:0,duration:0}:t.index<e.index?{...e,queue:n,index:e.index-1}:t.index>e.index?{...e,queue:n}:t.index<n.length?{...tk(e,t.index,e.playing),queue:n}:e.repeat===`all`?{...tk(e,0,e.playing),queue:n}:{...e,queue:n,index:n.length-1,playing:!1,position:0}}case`clear`:return{...e,queue:[],index:-1,playing:!1,position:0,duration:0};case`jump`:return Number.isInteger(t.index)&&t.index>=0&&t.index<=i?tk(e,t.index,!0):e;case`time`:return{...e,position:Math.max(0,t.position),duration:Math.max(0,t.duration)}}}var rk=(e,t)=>nk(e,t),ik=`friend.music`,ak=1e3,ok=1.5,sk=()=>{try{return JSON.parse(localStorage.getItem(ik)??`{}`)}catch{return{}}},ck=e=>{try{localStorage.setItem(ik,JSON.stringify({volume:e.volume,muted:e.muted,shuffle:e.shuffle,repeat:e.repeat,view:e.view}))}catch{}};function lk(e){switch(e.action){case`play`:return{type:`play`,tracks:e.tracks??[],mode:e.mode===`add`||e.mode===`next`?e.mode:`replace`,...e.shuffle?{shuffle:!0}:{}};case`pause`:case`resume`:case`toggle`:case`stop`:case`next`:case`previous`:return{type:e.action};case`seek`:return{type:`seek`,...e.seconds===void 0?{}:{seconds:e.seconds},...e.percent===void 0?{}:{percent:e.percent}};case`volume`:return{type:`volume`,...e.level===void 0?{}:{level:e.level},...e.delta===void 0?{}:{delta:e.delta}};case`mute`:return{type:`mute`,...e.on===void 0?{}:{on:e.on}};case`shuffle`:return{type:`shuffle`,...e.on===void 0?{}:{on:e.on}};case`repeat`:return e.mode===`off`||e.mode===`all`||e.mode===`one`?{type:`repeat`,mode:e.mode}:null;case`view`:return e.view?{type:`view`,view:e.view}:null;case`queue.remove`:return e.index===void 0?null:{type:`remove`,index:e.index};case`queue.clear`:return{type:`clear`};default:return null}}function uk({music:e,cmd:t,send:n,connection:r,createAudio:i}){let[a,o]=(0,l.useReducer)(rk,void 0,()=>{let e=sk();return QO({volume:e.volume??70,shuffle:e.shuffle??!1,repeat:e.repeat??`all`,view:e.view??`mini`})}),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(null),f=(0,l.useRef)(null),p=(0,l.useRef)(!1),m=(0,l.useRef)(a);m.current=a;let h=(0,l.useRef)(!1),g=(0,l.useRef)(null),_=(0,l.useRef)(0),v=(0,l.useRef)(!1);(0,l.useEffect)(()=>{if(!e||v.current)return;v.current=!0;let t=sk();o({type:`volume`,level:t.volume??e.volume}),o({type:`repeat`,mode:t.repeat??e.repeat}),(t.shuffle??e.shuffle)&&o({type:`shuffle`,on:!0}),o({type:`view`,view:t.view??e.startView}),t.muted&&o({type:`mute`,on:!0})},[e]);let y=()=>{if(!f.current){let e=i?i():new Audio;e.preload=`auto`,f.current=e}return f.current},b=(0,l.useRef)(!1),x=(0,l.useCallback)(()=>{let e=f.current;if(e&&e.src){b.current=!0;try{let t=e.play();t&&typeof t.then==`function`?t.then(()=>{b.current=!1,c(!1)},()=>{b.current=!1,c(!0)}):(b.current=!1,c(!1))}catch{b.current=!1,c(!0)}S.current||C()}},[]),S=(0,l.useRef)(!1),C=()=>{let e=f.current,t=typeof window<`u`?window.AudioContext??window.webkitAudioContext:void 0;if(e&&t&&typeof e.play==`function`)try{let n=new t,r=n.createMediaElementSource(e),i=n.createAnalyser();i.fftSize=256,i.smoothingTimeConstant=.82,r.connect(i),i.connect(n.destination),S.current=!0,d(i)}catch{S.current=!0}};(0,l.useEffect)(()=>{let e=y(),t=0,n=()=>{let n=Date.now();n-t<250||(t=n,o({type:`time`,position:e.currentTime||0,duration:Number.isFinite(e.duration)?e.duration:0}))},r=()=>o({type:`time`,position:e.currentTime||0,duration:Number.isFinite(e.duration)?e.duration:0}),i=()=>o({type:`ended`}),a=()=>o({type:`failed`});return e.addEventListener(`timeupdate`,n),e.addEventListener(`loadedmetadata`,r),e.addEventListener(`durationchange`,r),e.addEventListener(`ended`,i),e.addEventListener(`error`,a),()=>{e.removeEventListener(`timeupdate`,n),e.removeEventListener(`loadedmetadata`,r),e.removeEventListener(`durationchange`,r),e.removeEventListener(`ended`,i),e.removeEventListener(`error`,a),e.pause()}},[]);let w=a.index>=0?a.queue[a.index]??null:null;(0,l.useEffect)(()=>{let e=f.current;if(!e)return;let t=w?.id??null;if(t!==g.current){if(g.current=t,!t){e.pause(),e.src=``;return}e.src=`/api/music/track/${t}`,a.playing&&x()}},[w?.id,a.playing,x]),(0,l.useEffect)(()=>{let e=f.current;e&&e.src&&(a.playing&&e.paused&&!p.current&&!b.current?x():!a.playing&&!e.paused&&e.pause())},[a.playing,a.position,x]),(0,l.useEffect)(()=>{let e=f.current;e&&(e.volume=a.volume/100,e.muted=a.muted)},[a.volume,a.muted]),(0,l.useEffect)(()=>{let e=f.current;e&&e.src&&Math.abs((e.currentTime||0)-a.position)>ok&&(e.currentTime=a.position)},[a.position]),(0,l.useEffect)(()=>ck(a),[a.volume,a.muted,a.shuffle,a.repeat,a.view]),(0,l.useEffect)(()=>{if(!t||t.n===_.current)return;_.current=t.n;let e=lk(t.command);e&&o(e)},[t]),(0,l.useEffect)(()=>{let e=()=>{h.current=!0,p.current&&x()};return window.addEventListener(`pointerdown`,e,{passive:!0}),window.addEventListener(`keydown`,e),()=>{window.removeEventListener(`pointerdown`,e),window.removeEventListener(`keydown`,e)}},[x]),p.current=s;let T=(0,l.useRef)(0);return(0,l.useEffect)(()=>{if(r!==`open`)return;let e=()=>{let e=m.current,t=e.index>=0?e.queue[e.index]:void 0;T.current=Date.now(),n({type:`music.state`,state:{playing:e.playing,trackId:t?.id??null,title:t?.title??``,artist:t?.artist??``,album:t?.album??``,position:e.position,duration:e.duration,volume:e.volume,muted:e.muted,shuffle:e.shuffle,repeat:e.repeat,view:e.view,queue:e.queue.slice(0,50).map(e=>({id:e.id,title:e.title.slice(0,200)})),index:e.index,active:(typeof document>`u`||document.visibilityState===`visible`)&&h.current}})};e();let t=setInterval(()=>a.playing&&Date.now()-T.current>=ak&&e(),ak);return()=>clearInterval(t)},[r,w?.id,a.playing,a.volume,a.muted,a.shuffle,a.repeat,a.view,a.queue.length,a.index]),(0,l.useEffect)(()=>{let e=typeof navigator<`u`?navigator.mediaSession:void 0;if(e)try{w&&typeof MediaMetadata<`u`&&(e.metadata=new MediaMetadata({title:w.title,artist:w.artist,album:w.album,artwork:[{src:`/api/music/cover/${w.id}`}]})),e.playbackState=a.playing?`playing`:w?`paused`:`none`,e.setActionHandler(`play`,()=>o({type:`resume`})),e.setActionHandler(`pause`,()=>o({type:`pause`})),e.setActionHandler(`previoustrack`,()=>o({type:`previous`})),e.setActionHandler(`nexttrack`,()=>o({type:`next`})),e.setActionHandler(`seekto`,e=>typeof e.seekTime==`number`&&o({type:`seek`,seconds:e.seekTime}))}catch{}},[w?.id,a.playing]),{state:a,dispatch:o,current:w,blocked:s,analyser:u,unlock:x,audio:f}}function dk({onSignedOut:e}){let{state:t,send:n,dispatch:r,voice:i,useHere:a}=GD(e);rO(i),iO(i),uO(n,t.connection);let[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(!1),[d,f]=(0,l.useState)(!1),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(void 0),[v,y]=(0,l.useState)(null),[b,x]=(0,l.useState)(!1),[S,C]=(0,l.useState)(0),[w,T]=(0,l.useState)(null),E=de(t.view),D=uk({music:t.music,cmd:t.musicCmd,send:n,connection:t.connection}),O=t.hud?.animations??`full`,k=e=>{let{type:i,value:a}=e.action;if(i===`url`)window.open(a,`_blank`,`noopener,noreferrer`);else if(i===`prompt`)n({type:`chat.send`,text:a});else if(i===`music`||i===`panel`&&a===`music`){if(!t.music?.folderSet){r({type:`alert.add`,level:`info`,text:`No music folder is chosen yet. Pick one in Settings, Widgets, and the player opens.`}),y(`widgets`);return}if(i===`panel`){E.toggle(`music`,!0),D.state.view===`hidden`&&D.dispatch({type:`view`,view:`mini`});return}let e=lk({action:a});e&&D.dispatch(e)}else a===`plugins`?h(!0):a===`settings`?y(`model`):(a===`chat`||a===`tasks`)&&E.toggle(a,!0)},j=(0,l.useMemo)(()=>o?{...t,objects:[],captions:``}:t,[o,t]),ee=(0,l.useRef)(!1);(0,l.useEffect)(()=>{ee.current||!t.voice.available||t.voice.enrolled||(ee.current=!0,r({type:`alert.add`,level:`info`,text:`Voice recognition is not set up. Press Esc, then Enroll my voice.`}))},[t.voice.available,t.voice.enrolled,r]);let M=ne(),N=(0,l.useRef)(!1);(0,l.useEffect)(()=>{if(!M||N.current||t.connection!==`open`)return;N.current=!0;let e=!1;try{e=localStorage.getItem(`friend.touchHint`)===`1`,localStorage.setItem(`friend.touchHint`,`1`)}catch{}e||r({type:`alert.add`,level:`info`,text:`Hold the round mic button to talk, or tap it once to start and again to send. The keyboard button types; the menu button opens settings.`})},[M,t.connection,r]);let P=t.uiOpen?.n??0,te=t.uiOpen?.integration;(0,l.useEffect)(()=>{P!==0&&(_(te),h(!0))},[P,te]);let L=(0,l.useRef)(!1);(0,l.useEffect)(()=>{L.current||t.connection!==`open`||(L.current=!0,fetch(`/api/history`).then(e=>e.ok?e.json():[]).then(e=>r({type:`chat.seed`,lines:e})).catch(()=>{}))},[t.connection,r]),(0,l.useEffect)(()=>{t.connection===`open`&&n({type:`ui.panels`,open:[...E.show.chat?[`chat`]:[],...E.show.tasks?[`tasks`]:[]]})},[t.connection,E.show.chat,E.show.tasks,n]);let re=(0,l.useRef)(!1);(0,l.useEffect)(()=>{t.viewKnown&&t.view===`minimal`&&!re.current&&(re.current=!0,r({type:`alert.add`,level:`info`,text:`The view is Minimal, so the status line and clock are hidden. Press Esc, then View, to bring them back.`}))},[t.viewKnown,t.view,r]);let ie=e=>{ze.save({view:e}).catch(e=>r({type:`alert.add`,level:`warn`,text:e.message}))},ae=(0,l.useMemo)(()=>F({notify:e=>r({type:`alert.add`,level:`info`,text:e}),openSettings:()=>y(`model`),openLook:()=>y(`look`),openConnectors:()=>x(!0),openPlugins:()=>h(!0),openVoice:t.voice.available?()=>u(!0):null,muted:o,setMuted:s,cameraOn:t.camera.enabled,setCamera:e=>r({type:`camera.enable`,value:e}),clearScreen:()=>{for(let e of t.objects)n({type:`stage.event`,objectId:e.id,event:`dismiss`})},statusLine:()=>Ee({connection:t.connection,deviceOnline:t.deviceOnline,approval:t.approval,voiceMode:t.voice.mode,busy:t.busy,activity:t.activity}).text,endSession:t=>{fetch(t===`lock`?`/api/lock`:`/api/logout`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).catch(()=>{}).finally(e)},panelOn:e=>E.show[e],setPanel:(e,t)=>E.toggle(e,t),view:t.view,setView:ie,openHelp:T,resetLayout:()=>{ue(),window.location.reload()}}),[r,n,o,e,E.show,E.toggle,t.view,t.voice.available,t.voice.mode,t.camera.enabled,t.objects,t.connection,t.deviceOnline,t.approval,t.busy,t.activity]);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(kT,{state:j,send:n,dispatch:r,voice:i,slash:ae,onMenu:()=>C(e=>e+1)}),(0,p.jsxs)(ke,{approval:t.approval,challenge:t.challenge,cameraStream:t.camera.stream,alerts:t.alerts,connection:t.connection,deviceOnline:t.deviceOnline,voiceMode:t.voice.mode,busy:t.busy,activity:t.activity,showStatus:t.viewKnown&&E.show.status,showClock:t.viewKnown&&E.show.clock,profile:t.viewKnown&&E.show.profile?{ownerName:t.ownerName,speaker:t.speaker}:null,assistantName:t.assistantName,hud:t.hud,send:n,dispatch:r,children:[t.viewKnown&&E.show.chat&&(0,p.jsx)(fe,{lines:t.chat,live:t.chatLive,onSend:e=>n({type:`chat.send`,text:e}),onClose:()=>E.toggle(`chat`,!1)}),t.viewKnown&&E.show.tasks&&(0,p.jsx)(he,{busy:t.busy,onClose:()=>E.toggle(`tasks`,!1)}),t.viewKnown&&E.show.launcher&&t.hud&&(0,p.jsx)(xO,{items:t.hud.launcher,animations:O,onAction:k}),t.viewKnown&&E.show.music&&(0,p.jsx)(YO,{player:D,music:t.music,animations:O}),c&&(0,p.jsx)(QD,{onClose:()=>u(!1)}),d&&(0,p.jsx)(hO,{onClose:()=>f(!1)}),m&&(0,p.jsx)(Fu,{...g?{initialConfigure:g}:{},onClose:()=>{h(!1),_(void 0)}}),v&&(0,p.jsx)(Ab,{initialTab:v,onClose:()=>y(null)}),b&&(0,p.jsx)(A,{onClose:()=>x(!1)}),w&&(0,p.jsx)(I,{commands:w,onClose:()=>T(null)})]}),(0,p.jsx)(V,{muted:o,onToggleMute:()=>s(e=>!e),onSignedOut:e,voiceAvailable:t.voice.available,voiceEnrolled:t.voice.enrolled,onEnroll:()=>u(!0),onHousehold:()=>f(!0),onPlugins:()=>h(!0),onSettings:()=>y(`model`),onConnectors:()=>x(!0),cameraOn:t.camera.enabled,onToggleCamera:()=>r({type:`camera.enable`,value:!t.camera.enabled}),chatOn:E.show.chat,onToggleChat:()=>E.toggle(`chat`),tasksOn:E.show.tasks,onToggleTasks:()=>E.toggle(`tasks`),musicOn:E.show.music,onToggleMusic:()=>E.toggle(`music`),launcherOn:E.show.launcher,onToggleLauncher:()=>E.toggle(`launcher`),view:t.view,onView:ie,openRequest:S}),t.connection===`elsewhere`&&(0,p.jsx)(aO,{onUseHere:a})]})}function fk(){let[e,t]=(0,l.useState)(`loading`);return(0,l.useEffect)(()=>{let e=!0,n=n=>e&&t(n);return(async()=>{try{if(!(await(await fetch(`/api/state`)).json()).hasOwner)return n(`setup`);let e=await(await fetch(`/api/session`,{cache:`no-store`})).json();n(e.signedIn===!0?`stage`:`login`)}catch{n(`login`)}})(),()=>{e=!1}},[]),e===`loading`?(0,p.jsx)(`div`,{className:`boot`,"aria-busy":`true`}):e===`setup`?(0,p.jsx)(g,{onDone:()=>t(`login`)}):e===`login`?(0,p.jsx)(h,{onLoggedIn:()=>t(`stage`)}):(0,p.jsx)(dk,{onSignedOut:()=>t(`login`)})}(0,u.createRoot)(document.getElementById(`root`)).render((0,p.jsx)(l.StrictMode,{children:(0,p.jsx)(fk,{})}));
|
package/dist/web/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
9
9
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
10
10
|
<title>Friend</title>
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-DxMT-Znc.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-BNBo26fw.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "friend-assistant",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "A self-hosted personal AI assistant for your own PC: a full-screen stage, voice, tools with your approval, and your Claude subscription or a local model.",
|
|
5
5
|
"keywords": ["ai", "assistant", "jarvis", "voice", "claude", "ollama", "mcp", "self-hosted"],
|
|
6
6
|
"license": "UNLICENSED",
|