@frumu/tandem-panel 0.3.27 → 0.3.28
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.
|
@@ -0,0 +1,1335 @@
|
|
|
1
|
+
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const i of r)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&s(o)}).observe(document,{childList:!0,subtree:!0});function n(r){const i={};return r.integrity&&(i.integrity=r.integrity),r.referrerPolicy&&(i.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?i.credentials="include":r.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(r){if(r.ep)return;r.ep=!0;const i=n(r);fetch(r.href,i)}})();function k(e,t,n){function s(c,l){if(c._zod||Object.defineProperty(c,"_zod",{value:{def:l,constr:o,traits:new Set},enumerable:!1}),c._zod.traits.has(e))return;c._zod.traits.add(e),t(c,l);const d=o.prototype,p=Object.keys(d);for(let f=0;f<p.length;f++){const b=p[f];b in c||(c[b]=d[b].bind(c))}}const r=n?.Parent??Object;class i extends r{}Object.defineProperty(i,"name",{value:e});function o(c){var l;const d=n?.Parent?new i:this;s(d,c),(l=d._zod).deferred??(l.deferred=[]);for(const p of d._zod.deferred)p();return d}return Object.defineProperty(o,"init",{value:s}),Object.defineProperty(o,Symbol.hasInstance,{value:c=>n?.Parent&&c instanceof n.Parent?!0:c?._zod?.traits?.has(e)}),Object.defineProperty(o,"name",{value:e}),o}class gn extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class yo extends Error{constructor(t){super(`Encountered unidirectional transform during encode: ${t}`),this.name="ZodEncodeError"}}const bo={};function Ut(e){return bo}function wo(e){const t=Object.values(e).filter(s=>typeof s=="number");return Object.entries(e).filter(([s,r])=>t.indexOf(+s)===-1).map(([s,r])=>r)}function pr(e,t){return typeof t=="bigint"?t.toString():t}function Cr(e){return{get value(){{const t=e();return Object.defineProperty(this,"value",{value:t}),t}}}}function Rr(e){return e==null}function Mr(e){const t=e.startsWith("^")?1:0,n=e.endsWith("$")?e.length-1:e.length;return e.slice(t,n)}function xc(e,t){const n=(e.toString().split(".")[1]||"").length,s=t.toString();let r=(s.split(".")[1]||"").length;if(r===0&&/\d?e-\d?/.test(s)){const l=s.match(/\d?e-(\d?)/);l?.[1]&&(r=Number.parseInt(l[1]))}const i=n>r?n:r,o=Number.parseInt(e.toFixed(i).replace(".","")),c=Number.parseInt(t.toFixed(i).replace(".",""));return o%c/10**i}const ui=Symbol("evaluating");function ne(e,t,n){let s;Object.defineProperty(e,t,{get(){if(s!==ui)return s===void 0&&(s=ui,s=n()),s},set(r){Object.defineProperty(e,t,{value:r})},configurable:!0})}function tn(e,t,n){Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0})}function Bt(...e){const t={};for(const n of e){const s=Object.getOwnPropertyDescriptors(n);Object.assign(t,s)}return Object.defineProperties({},t)}function pi(e){return JSON.stringify(e)}function $c(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}const _o="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function Ss(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}const kc=Cr(()=>{if(typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{const e=Function;return new e(""),!0}catch{return!1}});function yn(e){if(Ss(e)===!1)return!1;const t=e.constructor;if(t===void 0||typeof t!="function")return!0;const n=t.prototype;return!(Ss(n)===!1||Object.prototype.hasOwnProperty.call(n,"isPrototypeOf")===!1)}function So(e){return yn(e)?{...e}:Array.isArray(e)?[...e]:e}const Tc=new Set(["string","number","symbol"]);function Ps(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Jt(e,t,n){const s=new e._zod.constr(t??e._zod.def);return(!t||n?.parent)&&(s._zod.parent=e),s}function H(e){const t=e;if(!t)return{};if(typeof t=="string")return{error:()=>t};if(t?.message!==void 0){if(t?.error!==void 0)throw new Error("Cannot specify both `message` and `error` params");t.error=t.message}return delete t.message,typeof t.error=="string"?{...t,error:()=>t.error}:t}function Ac(e){return Object.keys(e).filter(t=>e[t]._zod.optin==="optional"&&e[t]._zod.optout==="optional")}const Ec={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function Ic(e,t){const n=e._zod.def,s=n.checks;if(s&&s.length>0)throw new Error(".pick() cannot be used on object schemas containing refinements");const i=Bt(e._zod.def,{get shape(){const o={};for(const c in t){if(!(c in n.shape))throw new Error(`Unrecognized key: "${c}"`);t[c]&&(o[c]=n.shape[c])}return tn(this,"shape",o),o},checks:[]});return Jt(e,i)}function Cc(e,t){const n=e._zod.def,s=n.checks;if(s&&s.length>0)throw new Error(".omit() cannot be used on object schemas containing refinements");const i=Bt(e._zod.def,{get shape(){const o={...e._zod.def.shape};for(const c in t){if(!(c in n.shape))throw new Error(`Unrecognized key: "${c}"`);t[c]&&delete o[c]}return tn(this,"shape",o),o},checks:[]});return Jt(e,i)}function Rc(e,t){if(!yn(t))throw new Error("Invalid input to extend: expected a plain object");const n=e._zod.def.checks;if(n&&n.length>0){const i=e._zod.def.shape;for(const o in t)if(Object.getOwnPropertyDescriptor(i,o)!==void 0)throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}const r=Bt(e._zod.def,{get shape(){const i={...e._zod.def.shape,...t};return tn(this,"shape",i),i}});return Jt(e,r)}function Mc(e,t){if(!yn(t))throw new Error("Invalid input to safeExtend: expected a plain object");const n=Bt(e._zod.def,{get shape(){const s={...e._zod.def.shape,...t};return tn(this,"shape",s),s}});return Jt(e,n)}function Pc(e,t){const n=Bt(e._zod.def,{get shape(){const s={...e._zod.def.shape,...t._zod.def.shape};return tn(this,"shape",s),s},get catchall(){return t._zod.def.catchall},checks:[]});return Jt(e,n)}function zc(e,t,n){const r=t._zod.def.checks;if(r&&r.length>0)throw new Error(".partial() cannot be used on object schemas containing refinements");const o=Bt(t._zod.def,{get shape(){const c=t._zod.def.shape,l={...c};if(n)for(const d in n){if(!(d in c))throw new Error(`Unrecognized key: "${d}"`);n[d]&&(l[d]=e?new e({type:"optional",innerType:c[d]}):c[d])}else for(const d in c)l[d]=e?new e({type:"optional",innerType:c[d]}):c[d];return tn(this,"shape",l),l},checks:[]});return Jt(t,o)}function Oc(e,t,n){const s=Bt(t._zod.def,{get shape(){const r=t._zod.def.shape,i={...r};if(n)for(const o in n){if(!(o in i))throw new Error(`Unrecognized key: "${o}"`);n[o]&&(i[o]=new e({type:"nonoptional",innerType:r[o]}))}else for(const o in r)i[o]=new e({type:"nonoptional",innerType:r[o]});return tn(this,"shape",i),i}});return Jt(t,s)}function mn(e,t=0){if(e.aborted===!0)return!0;for(let n=t;n<e.issues.length;n++)if(e.issues[n]?.continue!==!0)return!0;return!1}function fn(e,t){return t.map(n=>{var s;return(s=n).path??(s.path=[]),n.path.unshift(e),n})}function ps(e){return typeof e=="string"?e:e?.message}function Zt(e,t,n){const s={...e,path:e.path??[]};if(!e.message){const r=ps(e.inst?._zod.def?.error?.(e))??ps(t?.error?.(e))??ps(n.customError?.(e))??ps(n.localeError?.(e))??"Invalid input";s.message=r}return delete s.inst,delete s.continue,t?.reportInput||delete s.input,s}function Pr(e){return Array.isArray(e)?"array":typeof e=="string"?"string":"unknown"}function Vn(...e){const[t,n,s]=e;return typeof t=="string"?{message:t,code:"custom",input:n,inst:s}:{...t}}const xo=(e,t)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:t,enumerable:!1}),e.message=JSON.stringify(t,pr,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},$o=k("$ZodError",xo),ko=k("$ZodError",xo,{Parent:Error});function Nc(e,t=n=>n.message){const n={},s=[];for(const r of e.issues)r.path.length>0?(n[r.path[0]]=n[r.path[0]]||[],n[r.path[0]].push(t(r))):s.push(t(r));return{formErrors:s,fieldErrors:n}}function Lc(e,t=n=>n.message){const n={_errors:[]},s=r=>{for(const i of r.issues)if(i.code==="invalid_union"&&i.errors.length)i.errors.map(o=>s({issues:o}));else if(i.code==="invalid_key")s({issues:i.issues});else if(i.code==="invalid_element")s({issues:i.issues});else if(i.path.length===0)n._errors.push(t(i));else{let o=n,c=0;for(;c<i.path.length;){const l=i.path[c];c===i.path.length-1?(o[l]=o[l]||{_errors:[]},o[l]._errors.push(t(i))):o[l]=o[l]||{_errors:[]},o=o[l],c++}}};return s(e),n}const zr=e=>(t,n,s,r)=>{const i=s?Object.assign(s,{async:!1}):{async:!1},o=t._zod.run({value:n,issues:[]},i);if(o instanceof Promise)throw new gn;if(o.issues.length){const c=new(r?.Err??e)(o.issues.map(l=>Zt(l,i,Ut())));throw _o(c,r?.callee),c}return o.value},Or=e=>async(t,n,s,r)=>{const i=s?Object.assign(s,{async:!0}):{async:!0};let o=t._zod.run({value:n,issues:[]},i);if(o instanceof Promise&&(o=await o),o.issues.length){const c=new(r?.Err??e)(o.issues.map(l=>Zt(l,i,Ut())));throw _o(c,r?.callee),c}return o.value},zs=e=>(t,n,s)=>{const r=s?{...s,async:!1}:{async:!1},i=t._zod.run({value:n,issues:[]},r);if(i instanceof Promise)throw new gn;return i.issues.length?{success:!1,error:new(e??$o)(i.issues.map(o=>Zt(o,r,Ut())))}:{success:!0,data:i.value}},Dc=zs(ko),Os=e=>async(t,n,s)=>{const r=s?Object.assign(s,{async:!0}):{async:!0};let i=t._zod.run({value:n,issues:[]},r);return i instanceof Promise&&(i=await i),i.issues.length?{success:!1,error:new e(i.issues.map(o=>Zt(o,r,Ut())))}:{success:!0,data:i.value}},jc=Os(ko),qc=e=>(t,n,s)=>{const r=s?Object.assign(s,{direction:"backward"}):{direction:"backward"};return zr(e)(t,n,r)},Vc=e=>(t,n,s)=>zr(e)(t,n,s),Fc=e=>async(t,n,s)=>{const r=s?Object.assign(s,{direction:"backward"}):{direction:"backward"};return Or(e)(t,n,r)},Uc=e=>async(t,n,s)=>Or(e)(t,n,s),Zc=e=>(t,n,s)=>{const r=s?Object.assign(s,{direction:"backward"}):{direction:"backward"};return zs(e)(t,n,r)},Hc=e=>(t,n,s)=>zs(e)(t,n,s),Bc=e=>async(t,n,s)=>{const r=s?Object.assign(s,{direction:"backward"}):{direction:"backward"};return Os(e)(t,n,r)},Jc=e=>async(t,n,s)=>Os(e)(t,n,s),Kc=/^[cC][^\s-]{8,}$/,Wc=/^[0-9a-z]+$/,Gc=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Xc=/^[0-9a-vA-V]{20}$/,Yc=/^[A-Za-z0-9]{27}$/,Qc=/^[a-zA-Z0-9_-]{21}$/,el=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,tl=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,mi=e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,nl=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,sl="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";function rl(){return new RegExp(sl,"u")}const il=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ol=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,al=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,cl=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,ll=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,To=/^[A-Za-z0-9_-]*$/,dl=/^\+[1-9]\d{6,14}$/,Ao="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",ul=new RegExp(`^${Ao}$`);function Eo(e){const t="(?:[01]\\d|2[0-3]):[0-5]\\d";return typeof e.precision=="number"?e.precision===-1?`${t}`:e.precision===0?`${t}:[0-5]\\d`:`${t}:[0-5]\\d\\.\\d{${e.precision}}`:`${t}(?::[0-5]\\d(?:\\.\\d+)?)?`}function pl(e){return new RegExp(`^${Eo(e)}$`)}function ml(e){const t=Eo({precision:e.precision}),n=["Z"];e.local&&n.push(""),e.offset&&n.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const s=`${t}(?:${n.join("|")})`;return new RegExp(`^${Ao}T(?:${s})$`)}const fl=e=>{const t=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??""}}`:"[\\s\\S]*";return new RegExp(`^${t}$`)},hl=/^-?\d+$/,Io=/^-?\d+(?:\.\d+)?$/,gl=/^(?:true|false)$/i,vl=/^[^A-Z]*$/,yl=/^[^a-z]*$/,Ze=k("$ZodCheck",(e,t)=>{var n;e._zod??(e._zod={}),e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),Co={number:"number",bigint:"bigint",object:"date"},Ro=k("$ZodCheckLessThan",(e,t)=>{Ze.init(e,t);const n=Co[typeof t.value];e._zod.onattach.push(s=>{const r=s._zod.bag,i=(t.inclusive?r.maximum:r.exclusiveMaximum)??Number.POSITIVE_INFINITY;t.value<i&&(t.inclusive?r.maximum=t.value:r.exclusiveMaximum=t.value)}),e._zod.check=s=>{(t.inclusive?s.value<=t.value:s.value<t.value)||s.issues.push({origin:n,code:"too_big",maximum:typeof t.value=="object"?t.value.getTime():t.value,input:s.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),Mo=k("$ZodCheckGreaterThan",(e,t)=>{Ze.init(e,t);const n=Co[typeof t.value];e._zod.onattach.push(s=>{const r=s._zod.bag,i=(t.inclusive?r.minimum:r.exclusiveMinimum)??Number.NEGATIVE_INFINITY;t.value>i&&(t.inclusive?r.minimum=t.value:r.exclusiveMinimum=t.value)}),e._zod.check=s=>{(t.inclusive?s.value>=t.value:s.value>t.value)||s.issues.push({origin:n,code:"too_small",minimum:typeof t.value=="object"?t.value.getTime():t.value,input:s.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),bl=k("$ZodCheckMultipleOf",(e,t)=>{Ze.init(e,t),e._zod.onattach.push(n=>{var s;(s=n._zod.bag).multipleOf??(s.multipleOf=t.value)}),e._zod.check=n=>{if(typeof n.value!=typeof t.value)throw new Error("Cannot mix number and bigint in multiple_of check.");(typeof n.value=="bigint"?n.value%t.value===BigInt(0):xc(n.value,t.value)===0)||n.issues.push({origin:typeof n.value,code:"not_multiple_of",divisor:t.value,input:n.value,inst:e,continue:!t.abort})}}),wl=k("$ZodCheckNumberFormat",(e,t)=>{Ze.init(e,t),t.format=t.format||"float64";const n=t.format?.includes("int"),s=n?"int":"number",[r,i]=Ec[t.format];e._zod.onattach.push(o=>{const c=o._zod.bag;c.format=t.format,c.minimum=r,c.maximum=i,n&&(c.pattern=hl)}),e._zod.check=o=>{const c=o.value;if(n){if(!Number.isInteger(c)){o.issues.push({expected:s,format:t.format,code:"invalid_type",continue:!1,input:c,inst:e});return}if(!Number.isSafeInteger(c)){c>0?o.issues.push({input:c,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!t.abort}):o.issues.push({input:c,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!t.abort});return}}c<r&&o.issues.push({origin:"number",input:c,code:"too_small",minimum:r,inclusive:!0,inst:e,continue:!t.abort}),c>i&&o.issues.push({origin:"number",input:c,code:"too_big",maximum:i,inclusive:!0,inst:e,continue:!t.abort})}}),_l=k("$ZodCheckMaxLength",(e,t)=>{var n;Ze.init(e,t),(n=e._zod.def).when??(n.when=s=>{const r=s.value;return!Rr(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.maximum??Number.POSITIVE_INFINITY;t.maximum<r&&(s._zod.bag.maximum=t.maximum)}),e._zod.check=s=>{const r=s.value;if(r.length<=t.maximum)return;const o=Pr(r);s.issues.push({origin:o,code:"too_big",maximum:t.maximum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),Sl=k("$ZodCheckMinLength",(e,t)=>{var n;Ze.init(e,t),(n=e._zod.def).when??(n.when=s=>{const r=s.value;return!Rr(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.minimum??Number.NEGATIVE_INFINITY;t.minimum>r&&(s._zod.bag.minimum=t.minimum)}),e._zod.check=s=>{const r=s.value;if(r.length>=t.minimum)return;const o=Pr(r);s.issues.push({origin:o,code:"too_small",minimum:t.minimum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),xl=k("$ZodCheckLengthEquals",(e,t)=>{var n;Ze.init(e,t),(n=e._zod.def).when??(n.when=s=>{const r=s.value;return!Rr(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag;r.minimum=t.length,r.maximum=t.length,r.length=t.length}),e._zod.check=s=>{const r=s.value,i=r.length;if(i===t.length)return;const o=Pr(r),c=i>t.length;s.issues.push({origin:o,...c?{code:"too_big",maximum:t.length}:{code:"too_small",minimum:t.length},inclusive:!0,exact:!0,input:s.value,inst:e,continue:!t.abort})}}),Ns=k("$ZodCheckStringFormat",(e,t)=>{var n,s;Ze.init(e,t),e._zod.onattach.push(r=>{const i=r._zod.bag;i.format=t.format,t.pattern&&(i.patterns??(i.patterns=new Set),i.patterns.add(t.pattern))}),t.pattern?(n=e._zod).check??(n.check=r=>{t.pattern.lastIndex=0,!t.pattern.test(r.value)&&r.issues.push({origin:"string",code:"invalid_format",format:t.format,input:r.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})}):(s=e._zod).check??(s.check=()=>{})}),$l=k("$ZodCheckRegex",(e,t)=>{Ns.init(e,t),e._zod.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:"string",code:"invalid_format",format:"regex",input:n.value,pattern:t.pattern.toString(),inst:e,continue:!t.abort})}}),kl=k("$ZodCheckLowerCase",(e,t)=>{t.pattern??(t.pattern=vl),Ns.init(e,t)}),Tl=k("$ZodCheckUpperCase",(e,t)=>{t.pattern??(t.pattern=yl),Ns.init(e,t)}),Al=k("$ZodCheckIncludes",(e,t)=>{Ze.init(e,t);const n=Ps(t.includes),s=new RegExp(typeof t.position=="number"?`^.{${t.position}}${n}`:n);t.pattern=s,e._zod.onattach.push(r=>{const i=r._zod.bag;i.patterns??(i.patterns=new Set),i.patterns.add(s)}),e._zod.check=r=>{r.value.includes(t.includes,t.position)||r.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:t.includes,input:r.value,inst:e,continue:!t.abort})}}),El=k("$ZodCheckStartsWith",(e,t)=>{Ze.init(e,t);const n=new RegExp(`^${Ps(t.prefix)}.*`);t.pattern??(t.pattern=n),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(n)}),e._zod.check=s=>{s.value.startsWith(t.prefix)||s.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:t.prefix,input:s.value,inst:e,continue:!t.abort})}}),Il=k("$ZodCheckEndsWith",(e,t)=>{Ze.init(e,t);const n=new RegExp(`.*${Ps(t.suffix)}$`);t.pattern??(t.pattern=n),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(n)}),e._zod.check=s=>{s.value.endsWith(t.suffix)||s.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:t.suffix,input:s.value,inst:e,continue:!t.abort})}}),Cl=k("$ZodCheckOverwrite",(e,t)=>{Ze.init(e,t),e._zod.check=n=>{n.value=t.tx(n.value)}});class Rl{constructor(t=[]){this.content=[],this.indent=0,this&&(this.args=t)}indented(t){this.indent+=1,t(this),this.indent-=1}write(t){if(typeof t=="function"){t(this,{execution:"sync"}),t(this,{execution:"async"});return}const s=t.split(`
|
|
2
|
+
`).filter(o=>o),r=Math.min(...s.map(o=>o.length-o.trimStart().length)),i=s.map(o=>o.slice(r)).map(o=>" ".repeat(this.indent*2)+o);for(const o of i)this.content.push(o)}compile(){const t=Function,n=this?.args,r=[...(this?.content??[""]).map(i=>` ${i}`)];return new t(...n,r.join(`
|
|
3
|
+
`))}}const Ml={major:4,minor:3,patch:6},ce=k("$ZodType",(e,t)=>{var n;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=Ml;const s=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&s.unshift(e);for(const r of s)for(const i of r._zod.onattach)i(e);if(s.length===0)(n=e._zod).deferred??(n.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const r=(o,c,l)=>{let d=mn(o),p;for(const f of c){if(f._zod.def.when){if(!f._zod.def.when(o))continue}else if(d)continue;const b=o.issues.length,w=f._zod.check(o);if(w instanceof Promise&&l?.async===!1)throw new gn;if(p||w instanceof Promise)p=(p??Promise.resolve()).then(async()=>{await w,o.issues.length!==b&&(d||(d=mn(o,b)))});else{if(o.issues.length===b)continue;d||(d=mn(o,b))}}return p?p.then(()=>o):o},i=(o,c,l)=>{if(mn(o))return o.aborted=!0,o;const d=r(c,s,l);if(d instanceof Promise){if(l.async===!1)throw new gn;return d.then(p=>e._zod.parse(p,l))}return e._zod.parse(d,l)};e._zod.run=(o,c)=>{if(c.skipChecks)return e._zod.parse(o,c);if(c.direction==="backward"){const d=e._zod.parse({value:o.value,issues:[]},{...c,skipChecks:!0});return d instanceof Promise?d.then(p=>i(p,o,c)):i(d,o,c)}const l=e._zod.parse(o,c);if(l instanceof Promise){if(c.async===!1)throw new gn;return l.then(d=>r(d,s,c))}return r(l,s,c)}}ne(e,"~standard",()=>({validate:r=>{try{const i=Dc(e,r);return i.success?{value:i.data}:{issues:i.error?.issues}}catch{return jc(e,r).then(o=>o.success?{value:o.data}:{issues:o.error?.issues})}},vendor:"zod",version:1}))}),Nr=k("$ZodString",(e,t)=>{ce.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??fl(e._zod.bag),e._zod.parse=(n,s)=>{if(t.coerce)try{n.value=String(n.value)}catch{}return typeof n.value=="string"||n.issues.push({expected:"string",code:"invalid_type",input:n.value,inst:e}),n}}),oe=k("$ZodStringFormat",(e,t)=>{Ns.init(e,t),Nr.init(e,t)}),Pl=k("$ZodGUID",(e,t)=>{t.pattern??(t.pattern=tl),oe.init(e,t)}),zl=k("$ZodUUID",(e,t)=>{if(t.version){const s={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[t.version];if(s===void 0)throw new Error(`Invalid UUID version: "${t.version}"`);t.pattern??(t.pattern=mi(s))}else t.pattern??(t.pattern=mi());oe.init(e,t)}),Ol=k("$ZodEmail",(e,t)=>{t.pattern??(t.pattern=nl),oe.init(e,t)}),Nl=k("$ZodURL",(e,t)=>{oe.init(e,t),e._zod.check=n=>{try{const s=n.value.trim(),r=new URL(s);t.hostname&&(t.hostname.lastIndex=0,t.hostname.test(r.hostname)||n.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:t.hostname.source,input:n.value,inst:e,continue:!t.abort})),t.protocol&&(t.protocol.lastIndex=0,t.protocol.test(r.protocol.endsWith(":")?r.protocol.slice(0,-1):r.protocol)||n.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:t.protocol.source,input:n.value,inst:e,continue:!t.abort})),t.normalize?n.value=r.href:n.value=s;return}catch{n.issues.push({code:"invalid_format",format:"url",input:n.value,inst:e,continue:!t.abort})}}}),Ll=k("$ZodEmoji",(e,t)=>{t.pattern??(t.pattern=rl()),oe.init(e,t)}),Dl=k("$ZodNanoID",(e,t)=>{t.pattern??(t.pattern=Qc),oe.init(e,t)}),jl=k("$ZodCUID",(e,t)=>{t.pattern??(t.pattern=Kc),oe.init(e,t)}),ql=k("$ZodCUID2",(e,t)=>{t.pattern??(t.pattern=Wc),oe.init(e,t)}),Vl=k("$ZodULID",(e,t)=>{t.pattern??(t.pattern=Gc),oe.init(e,t)}),Fl=k("$ZodXID",(e,t)=>{t.pattern??(t.pattern=Xc),oe.init(e,t)}),Ul=k("$ZodKSUID",(e,t)=>{t.pattern??(t.pattern=Yc),oe.init(e,t)}),Zl=k("$ZodISODateTime",(e,t)=>{t.pattern??(t.pattern=ml(t)),oe.init(e,t)}),Hl=k("$ZodISODate",(e,t)=>{t.pattern??(t.pattern=ul),oe.init(e,t)}),Bl=k("$ZodISOTime",(e,t)=>{t.pattern??(t.pattern=pl(t)),oe.init(e,t)}),Jl=k("$ZodISODuration",(e,t)=>{t.pattern??(t.pattern=el),oe.init(e,t)}),Kl=k("$ZodIPv4",(e,t)=>{t.pattern??(t.pattern=il),oe.init(e,t),e._zod.bag.format="ipv4"}),Wl=k("$ZodIPv6",(e,t)=>{t.pattern??(t.pattern=ol),oe.init(e,t),e._zod.bag.format="ipv6",e._zod.check=n=>{try{new URL(`http://[${n.value}]`)}catch{n.issues.push({code:"invalid_format",format:"ipv6",input:n.value,inst:e,continue:!t.abort})}}}),Gl=k("$ZodCIDRv4",(e,t)=>{t.pattern??(t.pattern=al),oe.init(e,t)}),Xl=k("$ZodCIDRv6",(e,t)=>{t.pattern??(t.pattern=cl),oe.init(e,t),e._zod.check=n=>{const s=n.value.split("/");try{if(s.length!==2)throw new Error;const[r,i]=s;if(!i)throw new Error;const o=Number(i);if(`${o}`!==i)throw new Error;if(o<0||o>128)throw new Error;new URL(`http://[${r}]`)}catch{n.issues.push({code:"invalid_format",format:"cidrv6",input:n.value,inst:e,continue:!t.abort})}}});function Po(e){if(e==="")return!0;if(e.length%4!==0)return!1;try{return atob(e),!0}catch{return!1}}const Yl=k("$ZodBase64",(e,t)=>{t.pattern??(t.pattern=ll),oe.init(e,t),e._zod.bag.contentEncoding="base64",e._zod.check=n=>{Po(n.value)||n.issues.push({code:"invalid_format",format:"base64",input:n.value,inst:e,continue:!t.abort})}});function Ql(e){if(!To.test(e))return!1;const t=e.replace(/[-_]/g,s=>s==="-"?"+":"/"),n=t.padEnd(Math.ceil(t.length/4)*4,"=");return Po(n)}const ed=k("$ZodBase64URL",(e,t)=>{t.pattern??(t.pattern=To),oe.init(e,t),e._zod.bag.contentEncoding="base64url",e._zod.check=n=>{Ql(n.value)||n.issues.push({code:"invalid_format",format:"base64url",input:n.value,inst:e,continue:!t.abort})}}),td=k("$ZodE164",(e,t)=>{t.pattern??(t.pattern=dl),oe.init(e,t)});function nd(e,t=null){try{const n=e.split(".");if(n.length!==3)return!1;const[s]=n;if(!s)return!1;const r=JSON.parse(atob(s));return!("typ"in r&&r?.typ!=="JWT"||!r.alg||t&&(!("alg"in r)||r.alg!==t))}catch{return!1}}const sd=k("$ZodJWT",(e,t)=>{oe.init(e,t),e._zod.check=n=>{nd(n.value,t.alg)||n.issues.push({code:"invalid_format",format:"jwt",input:n.value,inst:e,continue:!t.abort})}}),zo=k("$ZodNumber",(e,t)=>{ce.init(e,t),e._zod.pattern=e._zod.bag.pattern??Io,e._zod.parse=(n,s)=>{if(t.coerce)try{n.value=Number(n.value)}catch{}const r=n.value;if(typeof r=="number"&&!Number.isNaN(r)&&Number.isFinite(r))return n;const i=typeof r=="number"?Number.isNaN(r)?"NaN":Number.isFinite(r)?void 0:"Infinity":void 0;return n.issues.push({expected:"number",code:"invalid_type",input:r,inst:e,...i?{received:i}:{}}),n}}),rd=k("$ZodNumberFormat",(e,t)=>{wl.init(e,t),zo.init(e,t)}),id=k("$ZodBoolean",(e,t)=>{ce.init(e,t),e._zod.pattern=gl,e._zod.parse=(n,s)=>{if(t.coerce)try{n.value=!!n.value}catch{}const r=n.value;return typeof r=="boolean"||n.issues.push({expected:"boolean",code:"invalid_type",input:r,inst:e}),n}}),od=k("$ZodAny",(e,t)=>{ce.init(e,t),e._zod.parse=n=>n}),ad=k("$ZodUnknown",(e,t)=>{ce.init(e,t),e._zod.parse=n=>n}),cd=k("$ZodNever",(e,t)=>{ce.init(e,t),e._zod.parse=(n,s)=>(n.issues.push({expected:"never",code:"invalid_type",input:n.value,inst:e}),n)});function fi(e,t,n){e.issues.length&&t.issues.push(...fn(n,e.issues)),t.value[n]=e.value}const ld=k("$ZodArray",(e,t)=>{ce.init(e,t),e._zod.parse=(n,s)=>{const r=n.value;if(!Array.isArray(r))return n.issues.push({expected:"array",code:"invalid_type",input:r,inst:e}),n;n.value=Array(r.length);const i=[];for(let o=0;o<r.length;o++){const c=r[o],l=t.element._zod.run({value:c,issues:[]},s);l instanceof Promise?i.push(l.then(d=>fi(d,n,o))):fi(l,n,o)}return i.length?Promise.all(i).then(()=>n):n}});function xs(e,t,n,s,r){if(e.issues.length){if(r&&!(n in s))return;t.issues.push(...fn(n,e.issues))}e.value===void 0?n in s&&(t.value[n]=void 0):t.value[n]=e.value}function Oo(e){const t=Object.keys(e.shape);for(const s of t)if(!e.shape?.[s]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${s}": expected a Zod schema`);const n=Ac(e.shape);return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}function No(e,t,n,s,r,i){const o=[],c=r.keySet,l=r.catchall._zod,d=l.def.type,p=l.optout==="optional";for(const f in t){if(c.has(f))continue;if(d==="never"){o.push(f);continue}const b=l.run({value:t[f],issues:[]},s);b instanceof Promise?e.push(b.then(w=>xs(w,n,f,t,p))):xs(b,n,f,t,p)}return o.length&&n.issues.push({code:"unrecognized_keys",keys:o,input:t,inst:i}),e.length?Promise.all(e).then(()=>n):n}const dd=k("$ZodObject",(e,t)=>{if(ce.init(e,t),!Object.getOwnPropertyDescriptor(t,"shape")?.get){const c=t.shape;Object.defineProperty(t,"shape",{get:()=>{const l={...c};return Object.defineProperty(t,"shape",{value:l}),l}})}const s=Cr(()=>Oo(t));ne(e._zod,"propValues",()=>{const c=t.shape,l={};for(const d in c){const p=c[d]._zod;if(p.values){l[d]??(l[d]=new Set);for(const f of p.values)l[d].add(f)}}return l});const r=Ss,i=t.catchall;let o;e._zod.parse=(c,l)=>{o??(o=s.value);const d=c.value;if(!r(d))return c.issues.push({expected:"object",code:"invalid_type",input:d,inst:e}),c;c.value={};const p=[],f=o.shape;for(const b of o.keys){const w=f[b],h=w._zod.optout==="optional",_=w._zod.run({value:d[b],issues:[]},l);_ instanceof Promise?p.push(_.then(A=>xs(A,c,b,d,h))):xs(_,c,b,d,h)}return i?No(p,d,c,l,s.value,e):p.length?Promise.all(p).then(()=>c):c}}),ud=k("$ZodObjectJIT",(e,t)=>{dd.init(e,t);const n=e._zod.parse,s=Cr(()=>Oo(t)),r=b=>{const w=new Rl(["shape","payload","ctx"]),h=s.value,_=V=>{const T=pi(V);return`shape[${T}]._zod.run({ value: input[${T}], issues: [] }, ctx)`};w.write("const input = payload.value;");const A=Object.create(null);let $=0;for(const V of h.keys)A[V]=`key_${$++}`;w.write("const newResult = {};");for(const V of h.keys){const T=A[V],S=pi(V),C=b[V]?._zod?.optout==="optional";w.write(`const ${T} = ${_(V)};`),C?w.write(`
|
|
4
|
+
if (${T}.issues.length) {
|
|
5
|
+
if (${S} in input) {
|
|
6
|
+
payload.issues = payload.issues.concat(${T}.issues.map(iss => ({
|
|
7
|
+
...iss,
|
|
8
|
+
path: iss.path ? [${S}, ...iss.path] : [${S}]
|
|
9
|
+
})));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (${T}.value === undefined) {
|
|
14
|
+
if (${S} in input) {
|
|
15
|
+
newResult[${S}] = undefined;
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
newResult[${S}] = ${T}.value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
`):w.write(`
|
|
22
|
+
if (${T}.issues.length) {
|
|
23
|
+
payload.issues = payload.issues.concat(${T}.issues.map(iss => ({
|
|
24
|
+
...iss,
|
|
25
|
+
path: iss.path ? [${S}, ...iss.path] : [${S}]
|
|
26
|
+
})));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (${T}.value === undefined) {
|
|
30
|
+
if (${S} in input) {
|
|
31
|
+
newResult[${S}] = undefined;
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
newResult[${S}] = ${T}.value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
`)}w.write("payload.value = newResult;"),w.write("return payload;");const O=w.compile();return(V,T)=>O(b,V,T)};let i;const o=Ss,c=!bo.jitless,d=c&&kc.value,p=t.catchall;let f;e._zod.parse=(b,w)=>{f??(f=s.value);const h=b.value;return o(h)?c&&d&&w?.async===!1&&w.jitless!==!0?(i||(i=r(t.shape)),b=i(b,w),p?No([],h,b,w,f,e):b):n(b,w):(b.issues.push({expected:"object",code:"invalid_type",input:h,inst:e}),b)}});function hi(e,t,n,s){for(const i of e)if(i.issues.length===0)return t.value=i.value,t;const r=e.filter(i=>!mn(i));return r.length===1?(t.value=r[0].value,r[0]):(t.issues.push({code:"invalid_union",input:t.value,inst:n,errors:e.map(i=>i.issues.map(o=>Zt(o,s,Ut())))}),t)}const pd=k("$ZodUnion",(e,t)=>{ce.init(e,t),ne(e._zod,"optin",()=>t.options.some(r=>r._zod.optin==="optional")?"optional":void 0),ne(e._zod,"optout",()=>t.options.some(r=>r._zod.optout==="optional")?"optional":void 0),ne(e._zod,"values",()=>{if(t.options.every(r=>r._zod.values))return new Set(t.options.flatMap(r=>Array.from(r._zod.values)))}),ne(e._zod,"pattern",()=>{if(t.options.every(r=>r._zod.pattern)){const r=t.options.map(i=>i._zod.pattern);return new RegExp(`^(${r.map(i=>Mr(i.source)).join("|")})$`)}});const n=t.options.length===1,s=t.options[0]._zod.run;e._zod.parse=(r,i)=>{if(n)return s(r,i);let o=!1;const c=[];for(const l of t.options){const d=l._zod.run({value:r.value,issues:[]},i);if(d instanceof Promise)c.push(d),o=!0;else{if(d.issues.length===0)return d;c.push(d)}}return o?Promise.all(c).then(l=>hi(l,r,e,i)):hi(c,r,e,i)}}),md=k("$ZodIntersection",(e,t)=>{ce.init(e,t),e._zod.parse=(n,s)=>{const r=n.value,i=t.left._zod.run({value:r,issues:[]},s),o=t.right._zod.run({value:r,issues:[]},s);return i instanceof Promise||o instanceof Promise?Promise.all([i,o]).then(([l,d])=>gi(n,l,d)):gi(n,i,o)}});function mr(e,t){if(e===t)return{valid:!0,data:e};if(e instanceof Date&&t instanceof Date&&+e==+t)return{valid:!0,data:e};if(yn(e)&&yn(t)){const n=Object.keys(t),s=Object.keys(e).filter(i=>n.indexOf(i)!==-1),r={...e,...t};for(const i of s){const o=mr(e[i],t[i]);if(!o.valid)return{valid:!1,mergeErrorPath:[i,...o.mergeErrorPath]};r[i]=o.data}return{valid:!0,data:r}}if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return{valid:!1,mergeErrorPath:[]};const n=[];for(let s=0;s<e.length;s++){const r=e[s],i=t[s],o=mr(r,i);if(!o.valid)return{valid:!1,mergeErrorPath:[s,...o.mergeErrorPath]};n.push(o.data)}return{valid:!0,data:n}}return{valid:!1,mergeErrorPath:[]}}function gi(e,t,n){const s=new Map;let r;for(const c of t.issues)if(c.code==="unrecognized_keys"){r??(r=c);for(const l of c.keys)s.has(l)||s.set(l,{}),s.get(l).l=!0}else e.issues.push(c);for(const c of n.issues)if(c.code==="unrecognized_keys")for(const l of c.keys)s.has(l)||s.set(l,{}),s.get(l).r=!0;else e.issues.push(c);const i=[...s].filter(([,c])=>c.l&&c.r).map(([c])=>c);if(i.length&&r&&e.issues.push({...r,keys:i}),mn(e))return e;const o=mr(t.value,n.value);if(!o.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(o.mergeErrorPath)}`);return e.value=o.data,e}const fd=k("$ZodRecord",(e,t)=>{ce.init(e,t),e._zod.parse=(n,s)=>{const r=n.value;if(!yn(r))return n.issues.push({expected:"record",code:"invalid_type",input:r,inst:e}),n;const i=[],o=t.keyType._zod.values;if(o){n.value={};const c=new Set;for(const d of o)if(typeof d=="string"||typeof d=="number"||typeof d=="symbol"){c.add(typeof d=="number"?d.toString():d);const p=t.valueType._zod.run({value:r[d],issues:[]},s);p instanceof Promise?i.push(p.then(f=>{f.issues.length&&n.issues.push(...fn(d,f.issues)),n.value[d]=f.value})):(p.issues.length&&n.issues.push(...fn(d,p.issues)),n.value[d]=p.value)}let l;for(const d in r)c.has(d)||(l=l??[],l.push(d));l&&l.length>0&&n.issues.push({code:"unrecognized_keys",input:r,inst:e,keys:l})}else{n.value={};for(const c of Reflect.ownKeys(r)){if(c==="__proto__")continue;let l=t.keyType._zod.run({value:c,issues:[]},s);if(l instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(typeof c=="string"&&Io.test(c)&&l.issues.length){const f=t.keyType._zod.run({value:Number(c),issues:[]},s);if(f instanceof Promise)throw new Error("Async schemas not supported in object keys currently");f.issues.length===0&&(l=f)}if(l.issues.length){t.mode==="loose"?n.value[c]=r[c]:n.issues.push({code:"invalid_key",origin:"record",issues:l.issues.map(f=>Zt(f,s,Ut())),input:c,path:[c],inst:e});continue}const p=t.valueType._zod.run({value:r[c],issues:[]},s);p instanceof Promise?i.push(p.then(f=>{f.issues.length&&n.issues.push(...fn(c,f.issues)),n.value[l.value]=f.value})):(p.issues.length&&n.issues.push(...fn(c,p.issues)),n.value[l.value]=p.value)}}return i.length?Promise.all(i).then(()=>n):n}}),hd=k("$ZodEnum",(e,t)=>{ce.init(e,t);const n=wo(t.entries),s=new Set(n);e._zod.values=s,e._zod.pattern=new RegExp(`^(${n.filter(r=>Tc.has(typeof r)).map(r=>typeof r=="string"?Ps(r):r.toString()).join("|")})$`),e._zod.parse=(r,i)=>{const o=r.value;return s.has(o)||r.issues.push({code:"invalid_value",values:n,input:o,inst:e}),r}}),gd=k("$ZodTransform",(e,t)=>{ce.init(e,t),e._zod.parse=(n,s)=>{if(s.direction==="backward")throw new yo(e.constructor.name);const r=t.transform(n.value,n);if(s.async)return(r instanceof Promise?r:Promise.resolve(r)).then(o=>(n.value=o,n));if(r instanceof Promise)throw new gn;return n.value=r,n}});function vi(e,t){return e.issues.length&&t===void 0?{issues:[],value:void 0}:e}const Lo=k("$ZodOptional",(e,t)=>{ce.init(e,t),e._zod.optin="optional",e._zod.optout="optional",ne(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),ne(e._zod,"pattern",()=>{const n=t.innerType._zod.pattern;return n?new RegExp(`^(${Mr(n.source)})?$`):void 0}),e._zod.parse=(n,s)=>{if(t.innerType._zod.optin==="optional"){const r=t.innerType._zod.run(n,s);return r instanceof Promise?r.then(i=>vi(i,n.value)):vi(r,n.value)}return n.value===void 0?n:t.innerType._zod.run(n,s)}}),vd=k("$ZodExactOptional",(e,t)=>{Lo.init(e,t),ne(e._zod,"values",()=>t.innerType._zod.values),ne(e._zod,"pattern",()=>t.innerType._zod.pattern),e._zod.parse=(n,s)=>t.innerType._zod.run(n,s)}),yd=k("$ZodNullable",(e,t)=>{ce.init(e,t),ne(e._zod,"optin",()=>t.innerType._zod.optin),ne(e._zod,"optout",()=>t.innerType._zod.optout),ne(e._zod,"pattern",()=>{const n=t.innerType._zod.pattern;return n?new RegExp(`^(${Mr(n.source)}|null)$`):void 0}),ne(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,null]):void 0),e._zod.parse=(n,s)=>n.value===null?n:t.innerType._zod.run(n,s)}),bd=k("$ZodDefault",(e,t)=>{ce.init(e,t),e._zod.optin="optional",ne(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(n,s)=>{if(s.direction==="backward")return t.innerType._zod.run(n,s);if(n.value===void 0)return n.value=t.defaultValue,n;const r=t.innerType._zod.run(n,s);return r instanceof Promise?r.then(i=>yi(i,t)):yi(r,t)}});function yi(e,t){return e.value===void 0&&(e.value=t.defaultValue),e}const wd=k("$ZodPrefault",(e,t)=>{ce.init(e,t),e._zod.optin="optional",ne(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(n,s)=>(s.direction==="backward"||n.value===void 0&&(n.value=t.defaultValue),t.innerType._zod.run(n,s))}),_d=k("$ZodNonOptional",(e,t)=>{ce.init(e,t),ne(e._zod,"values",()=>{const n=t.innerType._zod.values;return n?new Set([...n].filter(s=>s!==void 0)):void 0}),e._zod.parse=(n,s)=>{const r=t.innerType._zod.run(n,s);return r instanceof Promise?r.then(i=>bi(i,e)):bi(r,e)}});function bi(e,t){return!e.issues.length&&e.value===void 0&&e.issues.push({code:"invalid_type",expected:"nonoptional",input:e.value,inst:t}),e}const Sd=k("$ZodCatch",(e,t)=>{ce.init(e,t),ne(e._zod,"optin",()=>t.innerType._zod.optin),ne(e._zod,"optout",()=>t.innerType._zod.optout),ne(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(n,s)=>{if(s.direction==="backward")return t.innerType._zod.run(n,s);const r=t.innerType._zod.run(n,s);return r instanceof Promise?r.then(i=>(n.value=i.value,i.issues.length&&(n.value=t.catchValue({...n,error:{issues:i.issues.map(o=>Zt(o,s,Ut()))},input:n.value}),n.issues=[]),n)):(n.value=r.value,r.issues.length&&(n.value=t.catchValue({...n,error:{issues:r.issues.map(i=>Zt(i,s,Ut()))},input:n.value}),n.issues=[]),n)}}),xd=k("$ZodPipe",(e,t)=>{ce.init(e,t),ne(e._zod,"values",()=>t.in._zod.values),ne(e._zod,"optin",()=>t.in._zod.optin),ne(e._zod,"optout",()=>t.out._zod.optout),ne(e._zod,"propValues",()=>t.in._zod.propValues),e._zod.parse=(n,s)=>{if(s.direction==="backward"){const i=t.out._zod.run(n,s);return i instanceof Promise?i.then(o=>ms(o,t.in,s)):ms(i,t.in,s)}const r=t.in._zod.run(n,s);return r instanceof Promise?r.then(i=>ms(i,t.out,s)):ms(r,t.out,s)}});function ms(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues},n)}const $d=k("$ZodReadonly",(e,t)=>{ce.init(e,t),ne(e._zod,"propValues",()=>t.innerType._zod.propValues),ne(e._zod,"values",()=>t.innerType._zod.values),ne(e._zod,"optin",()=>t.innerType?._zod?.optin),ne(e._zod,"optout",()=>t.innerType?._zod?.optout),e._zod.parse=(n,s)=>{if(s.direction==="backward")return t.innerType._zod.run(n,s);const r=t.innerType._zod.run(n,s);return r instanceof Promise?r.then(wi):wi(r)}});function wi(e){return e.value=Object.freeze(e.value),e}const kd=k("$ZodCustom",(e,t)=>{Ze.init(e,t),ce.init(e,t),e._zod.parse=(n,s)=>n,e._zod.check=n=>{const s=n.value,r=t.fn(s);if(r instanceof Promise)return r.then(i=>_i(i,n,s,e));_i(r,n,s,e)}});function _i(e,t,n,s){if(!e){const r={code:"custom",input:n,inst:s,path:[...s._zod.def.path??[]],continue:!s._zod.def.abort};s._zod.def.params&&(r.params=s._zod.def.params),t.issues.push(Vn(r))}}var Si;class Td{constructor(){this._map=new WeakMap,this._idmap=new Map}add(t,...n){const s=n[0];return this._map.set(t,s),s&&typeof s=="object"&&"id"in s&&this._idmap.set(s.id,t),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(t){const n=this._map.get(t);return n&&typeof n=="object"&&"id"in n&&this._idmap.delete(n.id),this._map.delete(t),this}get(t){const n=t._zod.parent;if(n){const s={...this.get(n)??{}};delete s.id;const r={...s,...this._map.get(t)};return Object.keys(r).length?r:void 0}return this._map.get(t)}has(t){return this._map.has(t)}}function Ad(){return new Td}(Si=globalThis).__zod_globalRegistry??(Si.__zod_globalRegistry=Ad());const Nn=globalThis.__zod_globalRegistry;function Ed(e,t){return new e({type:"string",...H(t)})}function Id(e,t){return new e({type:"string",format:"email",check:"string_format",abort:!1,...H(t)})}function xi(e,t){return new e({type:"string",format:"guid",check:"string_format",abort:!1,...H(t)})}function Cd(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,...H(t)})}function Rd(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...H(t)})}function Md(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...H(t)})}function Pd(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...H(t)})}function zd(e,t){return new e({type:"string",format:"url",check:"string_format",abort:!1,...H(t)})}function Od(e,t){return new e({type:"string",format:"emoji",check:"string_format",abort:!1,...H(t)})}function Nd(e,t){return new e({type:"string",format:"nanoid",check:"string_format",abort:!1,...H(t)})}function Ld(e,t){return new e({type:"string",format:"cuid",check:"string_format",abort:!1,...H(t)})}function Dd(e,t){return new e({type:"string",format:"cuid2",check:"string_format",abort:!1,...H(t)})}function jd(e,t){return new e({type:"string",format:"ulid",check:"string_format",abort:!1,...H(t)})}function qd(e,t){return new e({type:"string",format:"xid",check:"string_format",abort:!1,...H(t)})}function Vd(e,t){return new e({type:"string",format:"ksuid",check:"string_format",abort:!1,...H(t)})}function Fd(e,t){return new e({type:"string",format:"ipv4",check:"string_format",abort:!1,...H(t)})}function Ud(e,t){return new e({type:"string",format:"ipv6",check:"string_format",abort:!1,...H(t)})}function Zd(e,t){return new e({type:"string",format:"cidrv4",check:"string_format",abort:!1,...H(t)})}function Hd(e,t){return new e({type:"string",format:"cidrv6",check:"string_format",abort:!1,...H(t)})}function Bd(e,t){return new e({type:"string",format:"base64",check:"string_format",abort:!1,...H(t)})}function Jd(e,t){return new e({type:"string",format:"base64url",check:"string_format",abort:!1,...H(t)})}function Kd(e,t){return new e({type:"string",format:"e164",check:"string_format",abort:!1,...H(t)})}function Wd(e,t){return new e({type:"string",format:"jwt",check:"string_format",abort:!1,...H(t)})}function Gd(e,t){return new e({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...H(t)})}function Xd(e,t){return new e({type:"string",format:"date",check:"string_format",...H(t)})}function Yd(e,t){return new e({type:"string",format:"time",check:"string_format",precision:null,...H(t)})}function Qd(e,t){return new e({type:"string",format:"duration",check:"string_format",...H(t)})}function eu(e,t){return new e({type:"number",checks:[],...H(t)})}function tu(e,t){return new e({type:"number",check:"number_format",abort:!1,format:"safeint",...H(t)})}function nu(e,t){return new e({type:"boolean",...H(t)})}function su(e){return new e({type:"any"})}function ru(e){return new e({type:"unknown"})}function iu(e,t){return new e({type:"never",...H(t)})}function $i(e,t){return new Ro({check:"less_than",...H(t),value:e,inclusive:!1})}function tr(e,t){return new Ro({check:"less_than",...H(t),value:e,inclusive:!0})}function ki(e,t){return new Mo({check:"greater_than",...H(t),value:e,inclusive:!1})}function nr(e,t){return new Mo({check:"greater_than",...H(t),value:e,inclusive:!0})}function Ti(e,t){return new bl({check:"multiple_of",...H(t),value:e})}function Do(e,t){return new _l({check:"max_length",...H(t),maximum:e})}function $s(e,t){return new Sl({check:"min_length",...H(t),minimum:e})}function jo(e,t){return new xl({check:"length_equals",...H(t),length:e})}function ou(e,t){return new $l({check:"string_format",format:"regex",...H(t),pattern:e})}function au(e){return new kl({check:"string_format",format:"lowercase",...H(e)})}function cu(e){return new Tl({check:"string_format",format:"uppercase",...H(e)})}function lu(e,t){return new Al({check:"string_format",format:"includes",...H(t),includes:e})}function du(e,t){return new El({check:"string_format",format:"starts_with",...H(t),prefix:e})}function uu(e,t){return new Il({check:"string_format",format:"ends_with",...H(t),suffix:e})}function Sn(e){return new Cl({check:"overwrite",tx:e})}function pu(e){return Sn(t=>t.normalize(e))}function mu(){return Sn(e=>e.trim())}function fu(){return Sn(e=>e.toLowerCase())}function hu(){return Sn(e=>e.toUpperCase())}function gu(){return Sn(e=>$c(e))}function vu(e,t,n){return new e({type:"array",element:t,...H(n)})}function yu(e,t,n){return new e({type:"custom",check:"custom",fn:t,...H(n)})}function bu(e){const t=wu(n=>(n.addIssue=s=>{if(typeof s=="string")n.issues.push(Vn(s,n.value,t._zod.def));else{const r=s;r.fatal&&(r.continue=!1),r.code??(r.code="custom"),r.input??(r.input=n.value),r.inst??(r.inst=t),r.continue??(r.continue=!t._zod.def.abort),n.issues.push(Vn(r))}},e(n.value,n)));return t}function wu(e,t){const n=new Ze({check:"custom",...H(t)});return n._zod.check=e,n}function qo(e){let t=e?.target??"draft-2020-12";return t==="draft-4"&&(t="draft-04"),t==="draft-7"&&(t="draft-07"),{processors:e.processors??{},metadataRegistry:e?.metadata??Nn,target:t,unrepresentable:e?.unrepresentable??"throw",override:e?.override??(()=>{}),io:e?.io??"output",counter:0,seen:new Map,cycles:e?.cycles??"ref",reused:e?.reused??"inline",external:e?.external??void 0}}function ye(e,t,n={path:[],schemaPath:[]}){var s;const r=e._zod.def,i=t.seen.get(e);if(i)return i.count++,n.schemaPath.includes(e)&&(i.cycle=n.path),i.schema;const o={schema:{},count:1,cycle:void 0,path:n.path};t.seen.set(e,o);const c=e._zod.toJSONSchema?.();if(c)o.schema=c;else{const p={...n,schemaPath:[...n.schemaPath,e],path:n.path};if(e._zod.processJSONSchema)e._zod.processJSONSchema(t,o.schema,p);else{const b=o.schema,w=t.processors[r.type];if(!w)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${r.type}`);w(e,t,b,p)}const f=e._zod.parent;f&&(o.ref||(o.ref=f),ye(f,t,p),t.seen.get(f).isParent=!0)}const l=t.metadataRegistry.get(e);return l&&Object.assign(o.schema,l),t.io==="input"&&De(e)&&(delete o.schema.examples,delete o.schema.default),t.io==="input"&&o.schema._prefault&&((s=o.schema).default??(s.default=o.schema._prefault)),delete o.schema._prefault,t.seen.get(e).schema}function Vo(e,t){const n=e.seen.get(t);if(!n)throw new Error("Unprocessed schema. This is a bug in Zod.");const s=new Map;for(const o of e.seen.entries()){const c=e.metadataRegistry.get(o[0])?.id;if(c){const l=s.get(c);if(l&&l!==o[0])throw new Error(`Duplicate schema id "${c}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);s.set(c,o[0])}}const r=o=>{const c=e.target==="draft-2020-12"?"$defs":"definitions";if(e.external){const f=e.external.registry.get(o[0])?.id,b=e.external.uri??(h=>h);if(f)return{ref:b(f)};const w=o[1].defId??o[1].schema.id??`schema${e.counter++}`;return o[1].defId=w,{defId:w,ref:`${b("__shared")}#/${c}/${w}`}}if(o[1]===n)return{ref:"#"};const d=`#/${c}/`,p=o[1].schema.id??`__schema${e.counter++}`;return{defId:p,ref:d+p}},i=o=>{if(o[1].schema.$ref)return;const c=o[1],{ref:l,defId:d}=r(o);c.def={...c.schema},d&&(c.defId=d);const p=c.schema;for(const f in p)delete p[f];p.$ref=l};if(e.cycles==="throw")for(const o of e.seen.entries()){const c=o[1];if(c.cycle)throw new Error(`Cycle detected: #/${c.cycle?.join("/")}/<root>
|
|
38
|
+
|
|
39
|
+
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const o of e.seen.entries()){const c=o[1];if(t===o[0]){i(o);continue}if(e.external){const d=e.external.registry.get(o[0])?.id;if(t!==o[0]&&d){i(o);continue}}if(e.metadataRegistry.get(o[0])?.id){i(o);continue}if(c.cycle){i(o);continue}if(c.count>1&&e.reused==="ref"){i(o);continue}}}function Fo(e,t){const n=e.seen.get(t);if(!n)throw new Error("Unprocessed schema. This is a bug in Zod.");const s=o=>{const c=e.seen.get(o);if(c.ref===null)return;const l=c.def??c.schema,d={...l},p=c.ref;if(c.ref=null,p){s(p);const b=e.seen.get(p),w=b.schema;if(w.$ref&&(e.target==="draft-07"||e.target==="draft-04"||e.target==="openapi-3.0")?(l.allOf=l.allOf??[],l.allOf.push(w)):Object.assign(l,w),Object.assign(l,d),o._zod.parent===p)for(const _ in l)_==="$ref"||_==="allOf"||_ in d||delete l[_];if(w.$ref&&b.def)for(const _ in l)_==="$ref"||_==="allOf"||_ in b.def&&JSON.stringify(l[_])===JSON.stringify(b.def[_])&&delete l[_]}const f=o._zod.parent;if(f&&f!==p){s(f);const b=e.seen.get(f);if(b?.schema.$ref&&(l.$ref=b.schema.$ref,b.def))for(const w in l)w==="$ref"||w==="allOf"||w in b.def&&JSON.stringify(l[w])===JSON.stringify(b.def[w])&&delete l[w]}e.override({zodSchema:o,jsonSchema:l,path:c.path??[]})};for(const o of[...e.seen.entries()].reverse())s(o[0]);const r={};if(e.target==="draft-2020-12"?r.$schema="https://json-schema.org/draft/2020-12/schema":e.target==="draft-07"?r.$schema="http://json-schema.org/draft-07/schema#":e.target==="draft-04"?r.$schema="http://json-schema.org/draft-04/schema#":e.target,e.external?.uri){const o=e.external.registry.get(t)?.id;if(!o)throw new Error("Schema is missing an `id` property");r.$id=e.external.uri(o)}Object.assign(r,n.def??n.schema);const i=e.external?.defs??{};for(const o of e.seen.entries()){const c=o[1];c.def&&c.defId&&(i[c.defId]=c.def)}e.external||Object.keys(i).length>0&&(e.target==="draft-2020-12"?r.$defs=i:r.definitions=i);try{const o=JSON.parse(JSON.stringify(r));return Object.defineProperty(o,"~standard",{value:{...t["~standard"],jsonSchema:{input:ks(t,"input",e.processors),output:ks(t,"output",e.processors)}},enumerable:!1,writable:!1}),o}catch{throw new Error("Error converting schema to JSON.")}}function De(e,t){const n=t??{seen:new Set};if(n.seen.has(e))return!1;n.seen.add(e);const s=e._zod.def;if(s.type==="transform")return!0;if(s.type==="array")return De(s.element,n);if(s.type==="set")return De(s.valueType,n);if(s.type==="lazy")return De(s.getter(),n);if(s.type==="promise"||s.type==="optional"||s.type==="nonoptional"||s.type==="nullable"||s.type==="readonly"||s.type==="default"||s.type==="prefault")return De(s.innerType,n);if(s.type==="intersection")return De(s.left,n)||De(s.right,n);if(s.type==="record"||s.type==="map")return De(s.keyType,n)||De(s.valueType,n);if(s.type==="pipe")return De(s.in,n)||De(s.out,n);if(s.type==="object"){for(const r in s.shape)if(De(s.shape[r],n))return!0;return!1}if(s.type==="union"){for(const r of s.options)if(De(r,n))return!0;return!1}if(s.type==="tuple"){for(const r of s.items)if(De(r,n))return!0;return!!(s.rest&&De(s.rest,n))}return!1}const _u=(e,t={})=>n=>{const s=qo({...n,processors:t});return ye(e,s),Vo(s,e),Fo(s,e)},ks=(e,t,n={})=>s=>{const{libraryOptions:r,target:i}=s??{},o=qo({...r??{},target:i,io:t,processors:n});return ye(e,o),Vo(o,e),Fo(o,e)},Su={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},xu=(e,t,n,s)=>{const r=n;r.type="string";const{minimum:i,maximum:o,format:c,patterns:l,contentEncoding:d}=e._zod.bag;if(typeof i=="number"&&(r.minLength=i),typeof o=="number"&&(r.maxLength=o),c&&(r.format=Su[c]??c,r.format===""&&delete r.format,c==="time"&&delete r.format),d&&(r.contentEncoding=d),l&&l.size>0){const p=[...l];p.length===1?r.pattern=p[0].source:p.length>1&&(r.allOf=[...p.map(f=>({...t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0"?{type:"string"}:{},pattern:f.source}))])}},$u=(e,t,n,s)=>{const r=n,{minimum:i,maximum:o,format:c,multipleOf:l,exclusiveMaximum:d,exclusiveMinimum:p}=e._zod.bag;typeof c=="string"&&c.includes("int")?r.type="integer":r.type="number",typeof p=="number"&&(t.target==="draft-04"||t.target==="openapi-3.0"?(r.minimum=p,r.exclusiveMinimum=!0):r.exclusiveMinimum=p),typeof i=="number"&&(r.minimum=i,typeof p=="number"&&t.target!=="draft-04"&&(p>=i?delete r.minimum:delete r.exclusiveMinimum)),typeof d=="number"&&(t.target==="draft-04"||t.target==="openapi-3.0"?(r.maximum=d,r.exclusiveMaximum=!0):r.exclusiveMaximum=d),typeof o=="number"&&(r.maximum=o,typeof d=="number"&&t.target!=="draft-04"&&(d<=o?delete r.maximum:delete r.exclusiveMaximum)),typeof l=="number"&&(r.multipleOf=l)},ku=(e,t,n,s)=>{n.type="boolean"},Tu=(e,t,n,s)=>{n.not={}},Au=(e,t,n,s)=>{},Eu=(e,t,n,s)=>{},Iu=(e,t,n,s)=>{const r=e._zod.def,i=wo(r.entries);i.every(o=>typeof o=="number")&&(n.type="number"),i.every(o=>typeof o=="string")&&(n.type="string"),n.enum=i},Cu=(e,t,n,s)=>{if(t.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},Ru=(e,t,n,s)=>{if(t.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},Mu=(e,t,n,s)=>{const r=n,i=e._zod.def,{minimum:o,maximum:c}=e._zod.bag;typeof o=="number"&&(r.minItems=o),typeof c=="number"&&(r.maxItems=c),r.type="array",r.items=ye(i.element,t,{...s,path:[...s.path,"items"]})},Pu=(e,t,n,s)=>{const r=n,i=e._zod.def;r.type="object",r.properties={};const o=i.shape;for(const d in o)r.properties[d]=ye(o[d],t,{...s,path:[...s.path,"properties",d]});const c=new Set(Object.keys(o)),l=new Set([...c].filter(d=>{const p=i.shape[d]._zod;return t.io==="input"?p.optin===void 0:p.optout===void 0}));l.size>0&&(r.required=Array.from(l)),i.catchall?._zod.def.type==="never"?r.additionalProperties=!1:i.catchall?i.catchall&&(r.additionalProperties=ye(i.catchall,t,{...s,path:[...s.path,"additionalProperties"]})):t.io==="output"&&(r.additionalProperties=!1)},zu=(e,t,n,s)=>{const r=e._zod.def,i=r.inclusive===!1,o=r.options.map((c,l)=>ye(c,t,{...s,path:[...s.path,i?"oneOf":"anyOf",l]}));i?n.oneOf=o:n.anyOf=o},Ou=(e,t,n,s)=>{const r=e._zod.def,i=ye(r.left,t,{...s,path:[...s.path,"allOf",0]}),o=ye(r.right,t,{...s,path:[...s.path,"allOf",1]}),c=d=>"allOf"in d&&Object.keys(d).length===1,l=[...c(i)?i.allOf:[i],...c(o)?o.allOf:[o]];n.allOf=l},Nu=(e,t,n,s)=>{const r=n,i=e._zod.def;r.type="object";const o=i.keyType,l=o._zod.bag?.patterns;if(i.mode==="loose"&&l&&l.size>0){const p=ye(i.valueType,t,{...s,path:[...s.path,"patternProperties","*"]});r.patternProperties={};for(const f of l)r.patternProperties[f.source]=p}else(t.target==="draft-07"||t.target==="draft-2020-12")&&(r.propertyNames=ye(i.keyType,t,{...s,path:[...s.path,"propertyNames"]})),r.additionalProperties=ye(i.valueType,t,{...s,path:[...s.path,"additionalProperties"]});const d=o._zod.values;if(d){const p=[...d].filter(f=>typeof f=="string"||typeof f=="number");p.length>0&&(r.required=p)}},Lu=(e,t,n,s)=>{const r=e._zod.def,i=ye(r.innerType,t,s),o=t.seen.get(e);t.target==="openapi-3.0"?(o.ref=r.innerType,n.nullable=!0):n.anyOf=[i,{type:"null"}]},Du=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType},ju=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType,n.default=JSON.parse(JSON.stringify(r.defaultValue))},qu=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType,t.io==="input"&&(n._prefault=JSON.parse(JSON.stringify(r.defaultValue)))},Vu=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType;let o;try{o=r.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}n.default=o},Fu=(e,t,n,s)=>{const r=e._zod.def,i=t.io==="input"?r.in._zod.def.type==="transform"?r.out:r.in:r.out;ye(i,t,s);const o=t.seen.get(e);o.ref=i},Uu=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType,n.readOnly=!0},Uo=(e,t,n,s)=>{const r=e._zod.def;ye(r.innerType,t,s);const i=t.seen.get(e);i.ref=r.innerType},Zu=k("ZodISODateTime",(e,t)=>{Zl.init(e,t),de.init(e,t)});function Hu(e){return Gd(Zu,e)}const Bu=k("ZodISODate",(e,t)=>{Hl.init(e,t),de.init(e,t)});function Ju(e){return Xd(Bu,e)}const Ku=k("ZodISOTime",(e,t)=>{Bl.init(e,t),de.init(e,t)});function Wu(e){return Yd(Ku,e)}const Gu=k("ZodISODuration",(e,t)=>{Jl.init(e,t),de.init(e,t)});function Xu(e){return Qd(Gu,e)}const Yu=(e,t)=>{$o.init(e,t),e.name="ZodError",Object.defineProperties(e,{format:{value:n=>Lc(e,n)},flatten:{value:n=>Nc(e,n)},addIssue:{value:n=>{e.issues.push(n),e.message=JSON.stringify(e.issues,pr,2)}},addIssues:{value:n=>{e.issues.push(...n),e.message=JSON.stringify(e.issues,pr,2)}},isEmpty:{get(){return e.issues.length===0}}})},at=k("ZodError",Yu,{Parent:Error}),Qu=zr(at),ep=Or(at),tp=zs(at),np=Os(at),sp=qc(at),rp=Vc(at),ip=Fc(at),op=Uc(at),ap=Zc(at),cp=Hc(at),lp=Bc(at),dp=Jc(at),le=k("ZodType",(e,t)=>(ce.init(e,t),Object.assign(e["~standard"],{jsonSchema:{input:ks(e,"input"),output:ks(e,"output")}}),e.toJSONSchema=_u(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.check=(...n)=>e.clone(Bt(t,{checks:[...t.checks??[],...n.map(s=>typeof s=="function"?{_zod:{check:s,def:{check:"custom"},onattach:[]}}:s)]}),{parent:!0}),e.with=e.check,e.clone=(n,s)=>Jt(e,n,s),e.brand=()=>e,e.register=((n,s)=>(n.add(e,s),e)),e.parse=(n,s)=>Qu(e,n,s,{callee:e.parse}),e.safeParse=(n,s)=>tp(e,n,s),e.parseAsync=async(n,s)=>ep(e,n,s,{callee:e.parseAsync}),e.safeParseAsync=async(n,s)=>np(e,n,s),e.spa=e.safeParseAsync,e.encode=(n,s)=>sp(e,n,s),e.decode=(n,s)=>rp(e,n,s),e.encodeAsync=async(n,s)=>ip(e,n,s),e.decodeAsync=async(n,s)=>op(e,n,s),e.safeEncode=(n,s)=>ap(e,n,s),e.safeDecode=(n,s)=>cp(e,n,s),e.safeEncodeAsync=async(n,s)=>lp(e,n,s),e.safeDecodeAsync=async(n,s)=>dp(e,n,s),e.refine=(n,s)=>e.check(im(n,s)),e.superRefine=n=>e.check(om(n)),e.overwrite=n=>e.check(Sn(n)),e.optional=()=>Ci(e),e.exactOptional=()=>Bp(e),e.nullable=()=>Ri(e),e.nullish=()=>Ci(Ri(e)),e.nonoptional=n=>Yp(e,n),e.array=()=>nn(e),e.or=n=>Dp([e,n]),e.and=n=>qp(e,n),e.transform=n=>Mi(e,Zp(n)),e.default=n=>Wp(e,n),e.prefault=n=>Xp(e,n),e.catch=n=>em(e,n),e.pipe=n=>Mi(e,n),e.readonly=()=>sm(e),e.describe=n=>{const s=e.clone();return Nn.add(s,{description:n}),s},Object.defineProperty(e,"description",{get(){return Nn.get(e)?.description},configurable:!0}),e.meta=(...n)=>{if(n.length===0)return Nn.get(e);const s=e.clone();return Nn.add(s,n[0]),s},e.isOptional=()=>e.safeParse(void 0).success,e.isNullable=()=>e.safeParse(null).success,e.apply=n=>n(e),e)),Zo=k("_ZodString",(e,t)=>{Nr.init(e,t),le.init(e,t),e._zod.processJSONSchema=(s,r,i)=>xu(e,s,r);const n=e._zod.bag;e.format=n.format??null,e.minLength=n.minimum??null,e.maxLength=n.maximum??null,e.regex=(...s)=>e.check(ou(...s)),e.includes=(...s)=>e.check(lu(...s)),e.startsWith=(...s)=>e.check(du(...s)),e.endsWith=(...s)=>e.check(uu(...s)),e.min=(...s)=>e.check($s(...s)),e.max=(...s)=>e.check(Do(...s)),e.length=(...s)=>e.check(jo(...s)),e.nonempty=(...s)=>e.check($s(1,...s)),e.lowercase=s=>e.check(au(s)),e.uppercase=s=>e.check(cu(s)),e.trim=()=>e.check(mu()),e.normalize=(...s)=>e.check(pu(...s)),e.toLowerCase=()=>e.check(fu()),e.toUpperCase=()=>e.check(hu()),e.slugify=()=>e.check(gu())}),up=k("ZodString",(e,t)=>{Nr.init(e,t),Zo.init(e,t),e.email=n=>e.check(Id(pp,n)),e.url=n=>e.check(zd(mp,n)),e.jwt=n=>e.check(Wd(Ep,n)),e.emoji=n=>e.check(Od(fp,n)),e.guid=n=>e.check(xi(Ai,n)),e.uuid=n=>e.check(Cd(fs,n)),e.uuidv4=n=>e.check(Rd(fs,n)),e.uuidv6=n=>e.check(Md(fs,n)),e.uuidv7=n=>e.check(Pd(fs,n)),e.nanoid=n=>e.check(Nd(hp,n)),e.guid=n=>e.check(xi(Ai,n)),e.cuid=n=>e.check(Ld(gp,n)),e.cuid2=n=>e.check(Dd(vp,n)),e.ulid=n=>e.check(jd(yp,n)),e.base64=n=>e.check(Bd(kp,n)),e.base64url=n=>e.check(Jd(Tp,n)),e.xid=n=>e.check(qd(bp,n)),e.ksuid=n=>e.check(Vd(wp,n)),e.ipv4=n=>e.check(Fd(_p,n)),e.ipv6=n=>e.check(Ud(Sp,n)),e.cidrv4=n=>e.check(Zd(xp,n)),e.cidrv6=n=>e.check(Hd($p,n)),e.e164=n=>e.check(Kd(Ap,n)),e.datetime=n=>e.check(Hu(n)),e.date=n=>e.check(Ju(n)),e.time=n=>e.check(Wu(n)),e.duration=n=>e.check(Xu(n))});function j(e){return Ed(up,e)}const de=k("ZodStringFormat",(e,t)=>{oe.init(e,t),Zo.init(e,t)}),pp=k("ZodEmail",(e,t)=>{Ol.init(e,t),de.init(e,t)}),Ai=k("ZodGUID",(e,t)=>{Pl.init(e,t),de.init(e,t)}),fs=k("ZodUUID",(e,t)=>{zl.init(e,t),de.init(e,t)}),mp=k("ZodURL",(e,t)=>{Nl.init(e,t),de.init(e,t)}),fp=k("ZodEmoji",(e,t)=>{Ll.init(e,t),de.init(e,t)}),hp=k("ZodNanoID",(e,t)=>{Dl.init(e,t),de.init(e,t)}),gp=k("ZodCUID",(e,t)=>{jl.init(e,t),de.init(e,t)}),vp=k("ZodCUID2",(e,t)=>{ql.init(e,t),de.init(e,t)}),yp=k("ZodULID",(e,t)=>{Vl.init(e,t),de.init(e,t)}),bp=k("ZodXID",(e,t)=>{Fl.init(e,t),de.init(e,t)}),wp=k("ZodKSUID",(e,t)=>{Ul.init(e,t),de.init(e,t)}),_p=k("ZodIPv4",(e,t)=>{Kl.init(e,t),de.init(e,t)}),Sp=k("ZodIPv6",(e,t)=>{Wl.init(e,t),de.init(e,t)}),xp=k("ZodCIDRv4",(e,t)=>{Gl.init(e,t),de.init(e,t)}),$p=k("ZodCIDRv6",(e,t)=>{Xl.init(e,t),de.init(e,t)}),kp=k("ZodBase64",(e,t)=>{Yl.init(e,t),de.init(e,t)}),Tp=k("ZodBase64URL",(e,t)=>{ed.init(e,t),de.init(e,t)}),Ap=k("ZodE164",(e,t)=>{td.init(e,t),de.init(e,t)}),Ep=k("ZodJWT",(e,t)=>{sd.init(e,t),de.init(e,t)}),Ho=k("ZodNumber",(e,t)=>{zo.init(e,t),le.init(e,t),e._zod.processJSONSchema=(s,r,i)=>$u(e,s,r),e.gt=(s,r)=>e.check(ki(s,r)),e.gte=(s,r)=>e.check(nr(s,r)),e.min=(s,r)=>e.check(nr(s,r)),e.lt=(s,r)=>e.check($i(s,r)),e.lte=(s,r)=>e.check(tr(s,r)),e.max=(s,r)=>e.check(tr(s,r)),e.int=s=>e.check(Ei(s)),e.safe=s=>e.check(Ei(s)),e.positive=s=>e.check(ki(0,s)),e.nonnegative=s=>e.check(nr(0,s)),e.negative=s=>e.check($i(0,s)),e.nonpositive=s=>e.check(tr(0,s)),e.multipleOf=(s,r)=>e.check(Ti(s,r)),e.step=(s,r)=>e.check(Ti(s,r)),e.finite=()=>e;const n=e._zod.bag;e.minValue=Math.max(n.minimum??Number.NEGATIVE_INFINITY,n.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,e.maxValue=Math.min(n.maximum??Number.POSITIVE_INFINITY,n.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,e.isInt=(n.format??"").includes("int")||Number.isSafeInteger(n.multipleOf??.5),e.isFinite=!0,e.format=n.format??null});function ot(e){return eu(Ho,e)}const Ip=k("ZodNumberFormat",(e,t)=>{rd.init(e,t),Ho.init(e,t)});function Ei(e){return tu(Ip,e)}const Cp=k("ZodBoolean",(e,t)=>{id.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>ku(e,n,s)});function Ls(e){return nu(Cp,e)}const Rp=k("ZodAny",(e,t)=>{od.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Au()});function Ds(){return su(Rp)}const Mp=k("ZodUnknown",(e,t)=>{ad.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Eu()});function Ii(){return ru(Mp)}const Pp=k("ZodNever",(e,t)=>{cd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Tu(e,n,s)});function zp(e){return iu(Pp,e)}const Op=k("ZodArray",(e,t)=>{ld.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Mu(e,n,s,r),e.element=t.element,e.min=(n,s)=>e.check($s(n,s)),e.nonempty=n=>e.check($s(1,n)),e.max=(n,s)=>e.check(Do(n,s)),e.length=(n,s)=>e.check(jo(n,s)),e.unwrap=()=>e.element});function nn(e,t){return vu(Op,e,t)}const Np=k("ZodObject",(e,t)=>{ud.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Pu(e,n,s,r),ne(e,"shape",()=>t.shape),e.keyof=()=>Fp(Object.keys(e._zod.def.shape)),e.catchall=n=>e.clone({...e._zod.def,catchall:n}),e.passthrough=()=>e.clone({...e._zod.def,catchall:Ii()}),e.loose=()=>e.clone({...e._zod.def,catchall:Ii()}),e.strict=()=>e.clone({...e._zod.def,catchall:zp()}),e.strip=()=>e.clone({...e._zod.def,catchall:void 0}),e.extend=n=>Rc(e,n),e.safeExtend=n=>Mc(e,n),e.merge=n=>Pc(e,n),e.pick=n=>Ic(e,n),e.omit=n=>Cc(e,n),e.partial=(...n)=>zc(Jo,e,n[0]),e.required=(...n)=>Oc(Ko,e,n[0])});function Oe(e,t){const n={type:"object",shape:e??{},...H(t)};return new Np(n)}const Lp=k("ZodUnion",(e,t)=>{pd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>zu(e,n,s,r),e.options=t.options});function Dp(e,t){return new Lp({type:"union",options:e,...H(t)})}const jp=k("ZodIntersection",(e,t)=>{md.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Ou(e,n,s,r)});function qp(e,t){return new jp({type:"intersection",left:e,right:t})}const Vp=k("ZodRecord",(e,t)=>{fd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Nu(e,n,s,r),e.keyType=t.keyType,e.valueType=t.valueType});function Bo(e,t,n){return new Vp({type:"record",keyType:e,valueType:t,...H(n)})}const fr=k("ZodEnum",(e,t)=>{hd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(s,r,i)=>Iu(e,s,r),e.enum=t.entries,e.options=Object.values(t.entries);const n=new Set(Object.keys(t.entries));e.extract=(s,r)=>{const i={};for(const o of s)if(n.has(o))i[o]=t.entries[o];else throw new Error(`Key ${o} not found in enum`);return new fr({...t,checks:[],...H(r),entries:i})},e.exclude=(s,r)=>{const i={...t.entries};for(const o of s)if(n.has(o))delete i[o];else throw new Error(`Key ${o} not found in enum`);return new fr({...t,checks:[],...H(r),entries:i})}});function Fp(e,t){const n=Array.isArray(e)?Object.fromEntries(e.map(s=>[s,s])):e;return new fr({type:"enum",entries:n,...H(t)})}const Up=k("ZodTransform",(e,t)=>{gd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Ru(e,n),e._zod.parse=(n,s)=>{if(s.direction==="backward")throw new yo(e.constructor.name);n.addIssue=i=>{if(typeof i=="string")n.issues.push(Vn(i,n.value,t));else{const o=i;o.fatal&&(o.continue=!1),o.code??(o.code="custom"),o.input??(o.input=n.value),o.inst??(o.inst=e),n.issues.push(Vn(o))}};const r=t.transform(n.value,n);return r instanceof Promise?r.then(i=>(n.value=i,n)):(n.value=r,n)}});function Zp(e){return new Up({type:"transform",transform:e})}const Jo=k("ZodOptional",(e,t)=>{Lo.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Uo(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function Ci(e){return new Jo({type:"optional",innerType:e})}const Hp=k("ZodExactOptional",(e,t)=>{vd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Uo(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function Bp(e){return new Hp({type:"optional",innerType:e})}const Jp=k("ZodNullable",(e,t)=>{yd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Lu(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function Ri(e){return new Jp({type:"nullable",innerType:e})}const Kp=k("ZodDefault",(e,t)=>{bd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>ju(e,n,s,r),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function Wp(e,t){return new Kp({type:"default",innerType:e,get defaultValue(){return typeof t=="function"?t():So(t)}})}const Gp=k("ZodPrefault",(e,t)=>{wd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>qu(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function Xp(e,t){return new Gp({type:"prefault",innerType:e,get defaultValue(){return typeof t=="function"?t():So(t)}})}const Ko=k("ZodNonOptional",(e,t)=>{_d.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Du(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function Yp(e,t){return new Ko({type:"nonoptional",innerType:e,...H(t)})}const Qp=k("ZodCatch",(e,t)=>{Sd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Vu(e,n,s,r),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function em(e,t){return new Qp({type:"catch",innerType:e,catchValue:typeof t=="function"?t:()=>t})}const tm=k("ZodPipe",(e,t)=>{xd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Fu(e,n,s,r),e.in=t.in,e.out=t.out});function Mi(e,t){return new tm({type:"pipe",in:e,out:t})}const nm=k("ZodReadonly",(e,t)=>{$d.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Uu(e,n,s,r),e.unwrap=()=>e._zod.def.innerType});function sm(e){return new nm({type:"readonly",innerType:e})}const rm=k("ZodCustom",(e,t)=>{kd.init(e,t),le.init(e,t),e._zod.processJSONSchema=(n,s,r)=>Cu(e,n)});function im(e,t={}){return yu(rm,e,t)}function om(e){return bu(e)}var am=class extends Error{constructor(e,t,n,s){super(`Tandem API Validation Error [${t}] at ${e}: ${n.length} issues found.`),this.endpoint=e,this.status=t,this.issues=n,this.rawSnippet=s,this.name="TandemValidationError"}},Pi=j().or(Oe({id:j().optional(),runID:j().optional(),runId:j().optional(),run_id:j().optional(),sessionID:j().optional(),sessionId:j().optional(),session_id:j().optional(),missionID:j().optional(),missionId:j().optional(),mission_id:j().optional(),instanceID:j().optional(),instanceId:j().optional(),instance_id:j().optional()})).transform(e=>typeof e=="string"?e:e.id||e.runID||e.runId||e.run_id||e.sessionID||e.sessionId||e.session_id||e.missionID||e.missionId||e.mission_id||e.instanceID||e.instanceId||e.instance_id);Ds().transform(e=>e);Bo(j(),Ds()).transform(e=>e);var cm=Oe({ready:Ls().optional(),phase:j().optional()}).passthrough(),ys=Oe({id:j(),title:j(),created_at_ms:ot().optional(),createdAtMs:ot().optional(),directory:j().optional(),workspace_root:j().optional(),workspaceRoot:j().optional(),archived:Ls().optional()}).passthrough().transform(e=>({...e,createdAtMs:e.created_at_ms??e.createdAtMs??0,workspaceRoot:e.workspace_root??e.workspaceRoot})),zi=Oe({sessions:nn(ys).optional().default([]),count:ot().optional().default(0)}).passthrough(),lm=Oe({active:Oe({runID:j().optional(),runId:j().optional(),run_id:j().optional(),attachEventStream:j().optional()}).passthrough().nullable().optional()}).passthrough().transform(e=>e.active?{active:{...e.active,runId:e.active.runId||e.active.runID||e.active.run_id}}:{active:null}),Wo=Oe({ok:Ls().optional(),runID:j().optional(),runId:j().optional(),run_id:j().optional(),status:j().optional()}).passthrough().transform(e=>({...e,runId:e.runId||e.runID||e.run_id})),Go=Oe({id:j().optional(),runID:j().optional(),runId:j().optional(),run_id:j().optional(),routine_id:j().optional(),automation_id:j().optional(),status:j().optional(),started_at_ms:ot().optional(),finished_at_ms:ot().optional()}).passthrough().transform(e=>({...e,runId:e.runId||e.runID||e.run_id,routineId:e.routine_id,automationId:e.automation_id,startedAtMs:e.started_at_ms,finishedAtMs:e.finished_at_ms}));Oe({ok:Ls().default(!0),rev:ot().optional()}).passthrough();var dm=Oe({key:j(),value:Ds(),rev:ot().optional(),updated_at_ms:ot().optional(),updated_by:j().optional()}).passthrough().transform(e=>({...e,updatedAtMs:e.updated_at_ms,updatedBy:e.updated_by})),um=Oe({items:nn(dm).optional().default([]),count:ot().optional().default(0)}).passthrough(),pm=Oe({id:j().optional(),text:j().optional(),content:j().optional(),user_id:j().optional(),userID:j().optional(),source_type:j().optional(),sourceType:j().optional(),tags:nn(j()).optional(),source:j().optional(),session_id:j().optional(),sessionID:j().optional(),run_id:j().optional(),runID:j().optional()}).passthrough().transform(e=>({...e,text:e.text||e.content,content:e.content||e.text,userId:e.userID||e.user_id,sourceType:e.sourceType||e.source_type,sessionId:e.session_id||e.sessionID,runId:e.run_id||e.runID})),mm=Oe({items:nn(pm).optional().default([]),count:ot().optional().default(0)}).passthrough(),fm=Oe({id:j(),text:j().optional(),content:j().optional(),score:ot().optional(),source_type:j().optional(),sourceType:j().optional(),run_id:j().optional(),runID:j().optional(),tags:nn(j()).optional()}).passthrough().transform(e=>({...e,text:e.text||e.content,content:e.content||e.text,sourceType:e.sourceType||e.source_type,runId:e.runID||e.run_id})),hm=Oe({results:nn(fm).optional().default([]),count:ot().optional().default(0)}).passthrough(),gm=Oe({type:j(),properties:Bo(j(),Ds()).optional().default({}),sessionID:j().optional(),session_id:j().optional(),sessionId:j().optional(),runID:j().optional(),run_id:j().optional(),runId:j().optional(),timestamp:j().optional()}).passthrough().transform(e=>({...e,properties:e.properties,sessionId:e.sessionId||e.sessionID||e.session_id,runId:e.runId||e.runID||e.run_id}));function Ue(e,t,n,s){const r=e.safeParse(t);if(!r.success){const i=JSON.stringify(t).substring(0,200);throw new am(n,s,r.error.issues,i)}return r.data}function vm(e){const t=e.trim();if(!t||t===": keep-alive"||t.startsWith(":"))return null;try{const n=JSON.parse(t),s=gm.safeParse(n);return s.success?s.data:null}catch{return null}}async function*Oi(e,t,n){const s=n?.connectTimeoutMs??3e4,r=new AbortController,i=setTimeout(()=>r.abort(),s),o=n?.signal?ym([r.signal,n.signal]):r.signal;let c;try{c=await fetch(e,{headers:{Accept:"text/event-stream",Authorization:`Bearer ${t}`,"Cache-Control":"no-cache"},signal:o})}finally{clearTimeout(i)}if(!c.ok){const f=await c.text().catch(()=>"");throw new Error(`SSE connect failed (${c.status} ${c.statusText}): ${f}`)}if(!c.body)throw new Error("SSE response has no body");const l=new TextDecoder,d=c.body.getReader();let p="";try{for(;;){const{done:f,value:b}=await d.read();if(f)break;p+=l.decode(b,{stream:!0});const w=p.split(`
|
|
40
|
+
`);p=w.pop()??"";let h="";for(const _ of w)if(_.startsWith("data:"))h+=_.slice(5).trimStart();else if(_===""&&h){const A=vm(h);A&&(yield A),h=""}}}finally{d.releaseLock()}}function ym(e){const t=new AbortController;for(const n of e){if(n.aborted){t.abort(n.reason);break}n.addEventListener("abort",()=>t.abort(n.reason),{once:!0})}return t.signal}var pn=e=>typeof e=="string"&&e.trim().length>0?e:null,bm=e=>{try{const t=Pi.parse(e);if(t)return t}catch{const t=e.run||null;if(t)try{const n=Pi.parse(t);if(n)return n}catch{}}throw new Error("Run ID missing in engine response")},wm=class{constructor(e){this.baseUrl=e.baseUrl.replace(/\/+$/,""),this.token=e.token,this.timeoutMs=e.timeoutMs??2e4;const t=this._request.bind(this);this.sessions=new _m(this.baseUrl,this.token,this.timeoutMs,t),this.permissions=new Sm(t),this.questions=new xm(t),this.providers=new $m(t),this.channels=new km(t),this.mcp=new Tm(t),this.routines=new Cm(t),this.automations=new Rm(t),this.memory=new Am(t),this.skills=new Em(t),this.resources=new Im(t),this.agentTeams=new Mm(t),this.missions=new Pm(t)}setToken(e){this.token=e,this.sessions.setToken(e)}async health(){const e=await this._request("/global/health");return Ue(cm,e,"/global/health",200)}async listToolIds(){return this._request("/tool/ids")}async listTools(){const e=await this._request("/tool");return Array.isArray(e)?e:[]}async executeTool(e,t){return this._request("/tool/execute",{method:"POST",body:JSON.stringify({tool:e,args:t??{}})})}stream(e,t,n){const s=new URLSearchParams({sessionID:e});t&&s.set("runID",t);const r=`${this.baseUrl}/event?${s.toString()}`;return Oi(r,this.token,n)}globalStream(e){const t=`${this.baseUrl}/global/event`;return Oi(t,this.token,e)}async runEvents(e,t){const n=new URLSearchParams;t?.sinceSeq!==void 0&&n.set("since_seq",String(t.sinceSeq)),t?.tail!==void 0&&n.set("tail",String(t.tail));const s=n.toString()?`?${n.toString()}`:"",r=await this._request(`/run/${encodeURIComponent(e)}/events${s}`);return Array.isArray(r)?r:[]}async _request(e,t={}){const n=new AbortController,s=setTimeout(()=>n.abort(),this.timeoutMs);let r;try{r=await fetch(`${this.baseUrl}${e}`,{...t,headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`,...t.headers??{}},signal:n.signal})}catch(i){throw i instanceof Error&&i.name==="AbortError"?new Error(`Request timed out after ${this.timeoutMs}ms: ${e}`):i}finally{clearTimeout(s)}if(r.status!==204){if(!r.ok){const i=await r.text().catch(()=>"");throw new Error(`Request failed (${r.status} ${r.statusText}): ${i}`)}return r.json()}}},_m=class{constructor(e,t,n,s){this.baseUrl=e,this.token=t,this.timeoutMs=n,this.req=s}setToken(e){this.token=e}async create(e={}){const t={title:e.title??"Tandem SDK Session",directory:e.directory??"."};return e.permissions&&(t.permission=e.permissions),e.model&&e.provider&&(t.model={providerID:e.provider,modelID:e.model},t.provider=e.provider),(await this.req("/session",{method:"POST",body:JSON.stringify(t)})).id}async list(e={}){const t=new URLSearchParams;e.q&&t.set("q",e.q),e.page!==void 0&&t.set("page",String(e.page)),e.pageSize!==void 0&&t.set("page_size",String(e.pageSize)),e.archived!==void 0&&t.set("archived",String(e.archived)),e.scope&&t.set("scope",e.scope),e.workspace&&t.set("workspace",e.workspace);const n=t.toString()?`?${t.toString()}`:"",s=await this.req(`/session${n}`);return Ue(zi,s,"/session",200)}async get(e){const t=await this.req(`/session/${encodeURIComponent(e)}`);return Ue(ys,t,`/session/${e}`,200)}async update(e,t){const n=await this.req(`/session/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify(t)});return Ue(ys,n,`/session/${e}`,200)}async archive(e){return this.update(e,{archived:!0})}async delete(e){await this.req(`/session/${encodeURIComponent(e)}`,{method:"DELETE"})}async messages(e){return this.req(`/session/${encodeURIComponent(e)}/message`)}async todos(e){const t=await this.req(`/session/${encodeURIComponent(e)}/todo`);return Array.isArray(t)?t:t.todos??[]}async activeRun(e){const t=await this.req(`/session/${encodeURIComponent(e)}/run`);return Ue(lm,t,`/session/${e}/run`,200)}async promptAsync(e,t,n){const s={parts:[{type:"text",text:t}]};n?.provider&&n?.model&&(s.model={providerID:n.provider,modelID:n.model});const r=`/session/${encodeURIComponent(e)}/prompt_async?return=run`,i=new AbortController,o=setTimeout(()=>i.abort(),this.timeoutMs);let c;try{c=await fetch(`${this.baseUrl}${r}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify(s),signal:i.signal})}finally{clearTimeout(o)}if(c.status===409){const p=(await c.json().catch(()=>({}))).activeRun,f=pn(p?.runID)||pn(p?.runId)||pn(p?.run_id);if(f)return{runId:f}}if(!c.ok){const d=await c.text().catch(()=>"");throw new Error(`promptAsync failed (${c.status}): ${d}`)}const l=await c.json();return{runId:bm(l)}}async promptSync(e,t){const n={parts:[{type:"text",text:t}]},s=await this.req(`/session/${encodeURIComponent(e)}/prompt_sync`,{method:"POST",body:JSON.stringify(n)});return pn(s.reply)||pn(s.text)||pn(s.output)||""}async abort(e){return this.req(`/session/${encodeURIComponent(e)}/abort`,{method:"POST",body:JSON.stringify({})})}async cancel(e){return this.req(`/session/${encodeURIComponent(e)}/cancel`,{method:"POST",body:JSON.stringify({})})}async cancelRun(e,t){return this.req(`/session/${encodeURIComponent(e)}/run/${encodeURIComponent(t)}/cancel`,{method:"POST",body:JSON.stringify({})})}async fork(e){const t=await this.req(`/session/${encodeURIComponent(e)}/fork`,{method:"POST",body:JSON.stringify({})});return Ue(ys,t,`/session/${e}/fork`,200)}async diff(e){return this.req(`/session/${encodeURIComponent(e)}/diff`)}async revert(e){return this.req(`/session/${encodeURIComponent(e)}/revert`,{method:"POST",body:JSON.stringify({})})}async unrevert(e){return this.req(`/session/${encodeURIComponent(e)}/unrevert`,{method:"POST",body:JSON.stringify({})})}async children(e){const t=await this.req(`/session/${encodeURIComponent(e)}/children`);return Ue(zi,t,`/session/${e}/children`,200).sessions}async summarize(e){return this.req(`/session/${encodeURIComponent(e)}/summarize`,{method:"POST",body:JSON.stringify({})})}async attach(e,t){return this.req(`/session/${encodeURIComponent(e)}/attach`,{method:"POST",body:JSON.stringify({target_workspace:t})})}},Sm=class{constructor(e){this.req=e}async list(){return this.req("/permission")}async reply(e,t){const n=await this.req(`/permission/${encodeURIComponent(e)}/reply`,{method:"POST",body:JSON.stringify({reply:t})});if(!n.ok)throw new Error(`Permission reply rejected: ${n.error??e}`);return{ok:!0}}},xm=class{constructor(e){this.req=e}async list(){const e=await this.req("/question");return Array.isArray(e)?{questions:e}:e}async reply(e,t){return this.req(`/question/${encodeURIComponent(e)}/reply`,{method:"POST",body:JSON.stringify({answer:t})})}async reject(e){return this.req(`/question/${encodeURIComponent(e)}/reject`,{method:"POST",body:JSON.stringify({})})}},$m=class{constructor(e){this.req=e}async catalog(){return this.req("/provider")}async config(){return this.req("/config/providers")}async setDefaults(e,t){await this.req("/config",{method:"PATCH",body:JSON.stringify({default_provider:e,providers:{[e]:{default_model:t}}})})}async setApiKey(e,t){await this.req(`/auth/${encodeURIComponent(e)}`,{method:"PUT",body:JSON.stringify({apiKey:t})})}async authStatus(){return this.req("/provider/auth")}},km=class{constructor(e){this.req=e}async config(){return this.req("/channels/config")}async status(){return this.req("/channels/status")}async put(e,t){return this.req(`/channels/${e}`,{method:"PUT",body:JSON.stringify(t)})}async delete(e){return this.req(`/channels/${e}`,{method:"DELETE"})}},Tm=class{constructor(e){this.req=e}async list(){return this.req("/mcp")}async listTools(){return this.req("/mcp/tools")}async listResources(){const e=await this.req("/mcp/resources");return Array.isArray(e)?e:[]}async add(e){return this.req("/mcp",{method:"POST",body:JSON.stringify(e)})}async connect(e){return this.req(`/mcp/${encodeURIComponent(e)}/connect`,{method:"POST"})}async disconnect(e){return this.req(`/mcp/${encodeURIComponent(e)}/disconnect`,{method:"POST"})}async refresh(e){return this.req(`/mcp/${encodeURIComponent(e)}/refresh`,{method:"POST"})}async setEnabled(e,t){return this.req(`/mcp/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({enabled:t})})}},Am=class{constructor(e){this.req=e}async put(e){return this.req("/memory/put",{method:"POST",body:JSON.stringify(e)})}async search(e){const t=await this.req("/memory/search",{method:"POST",body:JSON.stringify(e)});return Ue(hm,t,"/memory/search",200)}async list(e){const t=new URLSearchParams;e?.q&&t.set("q",e.q),e?.limit!==void 0&&t.set("limit",String(e.limit)),e?.offset!==void 0&&t.set("offset",String(e.offset)),e?.userId&&t.set("user_id",e.userId);const n=t.toString()?`?${t.toString()}`:"",s=await this.req(`/memory${n}`);return Ue(mm,s,"/memory",200)}async delete(e){return this.req(`/memory/${encodeURIComponent(e)}`,{method:"DELETE"})}async promote(e){return this.req("/memory/promote",{method:"POST",body:JSON.stringify(e)})}async demote(e){const t={id:e.id,run_id:e.runId};return this.req("/memory/demote",{method:"POST",body:JSON.stringify(t)})}async audit(e){const t=new URLSearchParams;e?.run_id&&t.set("run_id",e.run_id),e?.limit!==void 0&&t.set("limit",String(e.limit));const n=t.toString()?`?${t.toString()}`:"",s=await this.req(`/memory/audit${n}`);return Array.isArray(s)?{entries:s,count:s.length}:s}},Em=class{constructor(e){this.req=e}async list(e){const t=e?`?location=${encodeURIComponent(e)}`:"",n=await this.req(`/skills${t}`);return Array.isArray(n)?{skills:n,count:n.length}:n}async get(e){return this.req(`/skills/${encodeURIComponent(e)}`)}async import(e){return this.req("/skills/import",{method:"POST",body:JSON.stringify(e)})}async preview(e){return this.req("/skills/import/preview",{method:"POST",body:JSON.stringify(e)})}async templates(){const e=await this.req("/skills/templates");return Array.isArray(e)?{templates:e,count:e.length}:e}},Im=class{constructor(e){this.req=e}async list(e){const t=new URLSearchParams;e?.prefix&&t.set("prefix",e.prefix),e?.limit!==void 0&&t.set("limit",String(e.limit));const n=t.toString()?`?${t.toString()}`:"",s=await this.req(`/resource${n}`);return Ue(um,s,"/resource",200)}async write(e){return this.req("/resource",{method:"PUT",body:JSON.stringify(e)})}async delete(e,t){return this.req("/resource",{method:"DELETE",body:JSON.stringify({key:e,...t})})}},Cm=class{constructor(e){this.req=e}async list(){return this.req("/routines")}async create(e){const t={...e};return"prompt"in t&&!("entrypoint"in t)&&(t.entrypoint=t.prompt),this.req("/routines",{method:"POST",body:JSON.stringify(t)})}async update(e,t){return this.req(`/routines/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify(t)})}async delete(e){await this.req(`/routines/${encodeURIComponent(e)}`,{method:"DELETE"})}async runNow(e){const t=await this.req(`/routines/${encodeURIComponent(e)}/run_now`,{method:"POST",body:JSON.stringify({})});return Ue(Wo,t,`/routines/${e}/run_now`,200)}async listRuns(e){const t=new URLSearchParams;e?.routine_id&&t.set("routine_id",e.routine_id),e?.limit!==void 0&&t.set("limit",String(e.limit));const n=t.toString()?`?${t.toString()}`:"";return this.req(`/routines/runs${n}`)}async getRunsForRoutine(e,t=25){return this.req(`/routines/${encodeURIComponent(e)}/runs?limit=${t}`)}async getRun(e){const t=await this.req(`/routines/runs/${encodeURIComponent(e)}`);return Ue(Go,t,`/routines/runs/${e}`,200)}async listArtifacts(e){return this.req(`/routines/runs/${encodeURIComponent(e)}/artifacts`)}async approveRun(e,t){return this.req(`/routines/runs/${encodeURIComponent(e)}/approve`,{method:"POST",body:JSON.stringify({reason:t??""})})}async denyRun(e,t){return this.req(`/routines/runs/${encodeURIComponent(e)}/deny`,{method:"POST",body:JSON.stringify({reason:t??""})})}async pauseRun(e,t){return this.req(`/routines/runs/${encodeURIComponent(e)}/pause`,{method:"POST",body:JSON.stringify({reason:t??""})})}async resumeRun(e,t){return this.req(`/routines/runs/${encodeURIComponent(e)}/resume`,{method:"POST",body:JSON.stringify({reason:t??""})})}async history(e,t){const n=t!==void 0?`?limit=${t}`:"",s=await this.req(`/routines/${encodeURIComponent(e)}/history${n}`);return Array.isArray(s)?{history:s,count:s.length}:s}},Rm=class{constructor(e){this.req=e}async list(){return this.req("/automations")}async create(e){return this.req("/automations",{method:"POST",body:JSON.stringify(e)})}async update(e,t){return this.req(`/automations/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify(t)})}async delete(e){await this.req(`/automations/${encodeURIComponent(e)}`,{method:"DELETE"})}async runNow(e){const t=await this.req(`/automations/${encodeURIComponent(e)}/run_now`,{method:"POST",body:JSON.stringify({})});return Ue(Wo,t,`/automations/${e}/run_now`,200)}async listRuns(e){const t=new URLSearchParams;e?.automation_id&&t.set("automation_id",e.automation_id),e?.limit!==void 0&&t.set("limit",String(e.limit));const n=t.toString()?`?${t.toString()}`:"";return this.req(`/automations/runs${n}`)}async getRunsForAutomation(e,t=25){return this.req(`/automations/${encodeURIComponent(e)}/runs?limit=${t}`)}async getRun(e){const t=await this.req(`/automations/runs/${encodeURIComponent(e)}`);return Ue(Go,t,`/automations/runs/${e}`,200)}async listArtifacts(e){return this.req(`/automations/runs/${encodeURIComponent(e)}/artifacts`)}async approveRun(e,t){return this.req(`/automations/runs/${encodeURIComponent(e)}/approve`,{method:"POST",body:JSON.stringify({reason:t??""})})}async denyRun(e,t){return this.req(`/automations/runs/${encodeURIComponent(e)}/deny`,{method:"POST",body:JSON.stringify({reason:t??""})})}async pauseRun(e,t){return this.req(`/automations/runs/${encodeURIComponent(e)}/pause`,{method:"POST",body:JSON.stringify({reason:t??""})})}async resumeRun(e,t){return this.req(`/automations/runs/${encodeURIComponent(e)}/resume`,{method:"POST",body:JSON.stringify({reason:t??""})})}async history(e,t){const n=t!==void 0?`?limit=${t}`:"",s=await this.req(`/automations/${encodeURIComponent(e)}/history${n}`);return Array.isArray(s)?{history:s,count:s.length}:s}},Mm=class{constructor(e){this.req=e}async listTemplates(){return this.req("/agent-team/templates")}async listInstances(e){const t=new URLSearchParams;e?.missionID&&t.set("missionID",e.missionID),e?.parentInstanceID&&t.set("parentInstanceID",e.parentInstanceID),e?.status&&t.set("status",e.status);const n=t.toString()?`?${t.toString()}`:"";return this.req(`/agent-team/instances${n}`)}async listMissions(){return this.req("/agent-team/missions")}async listApprovals(){return this.req("/agent-team/approvals")}async spawn(e){return this.req("/agent-team/spawn",{method:"POST",body:JSON.stringify(e)})}async approveSpawn(e,t){return this.req(`/agent-team/approvals/spawn/${encodeURIComponent(e)}/approve`,{method:"POST",body:JSON.stringify({reason:t??""})})}async denySpawn(e,t){return this.req(`/agent-team/approvals/spawn/${encodeURIComponent(e)}/deny`,{method:"POST",body:JSON.stringify({reason:t??""})})}},Pm=class{constructor(e){this.req=e}async list(){return this.req("/mission")}async create(e){return this.req("/mission",{method:"POST",body:JSON.stringify(e)})}async get(e){return this.req(`/mission/${encodeURIComponent(e)}`)}async applyEvent(e,t){return this.req(`/mission/${encodeURIComponent(e)}/event`,{method:"POST",body:JSON.stringify({event:t})})}};const Qt=e=>e;let Xo=Qt;const js=(e,t,n)=>{const s=t-e;return s===0?1:(n-e)/s};function Lr(e){let t;return()=>(t===void 0&&(t=e()),t)}const zm=Lr(()=>window.ScrollTimeline!==void 0);class Om{constructor(t){this.stop=()=>this.runAll("stop"),this.animations=t.filter(Boolean)}get finished(){return Promise.all(this.animations.map(t=>"finished"in t?t.finished:t))}getAll(t){return this.animations[0][t]}setAll(t,n){for(let s=0;s<this.animations.length;s++)this.animations[s][t]=n}attachTimeline(t,n){const s=this.animations.map(r=>{if(zm()&&r.attachTimeline)return r.attachTimeline(t);if(typeof n=="function")return n(r)});return()=>{s.forEach((r,i)=>{r&&r(),this.animations[i].stop()})}}get time(){return this.getAll("time")}set time(t){this.setAll("time",t)}get speed(){return this.getAll("speed")}set speed(t){this.setAll("speed",t)}get startTime(){return this.getAll("startTime")}get duration(){let t=0;for(let n=0;n<this.animations.length;n++)t=Math.max(t,this.animations[n].duration);return t}runAll(t){this.animations.forEach(n=>n[t]())}flatten(){this.runAll("flatten")}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}class Yo extends Om{then(t,n){return Promise.all(this.animations).then(t).catch(n)}}const It=e=>e*1e3,Ct=e=>e/1e3,Ts=2e4;function Dr(e){let t=0;const n=50;let s=e.next(t);for(;!s.done&&t<Ts;)t+=n,s=e.next(t);return t>=Ts?1/0:t}const Qo=(e,t,n=10)=>{let s="";const r=Math.max(Math.round(t/n),2);for(let i=0;i<r;i++)s+=e(js(0,r-1,i))+", ";return`linear(${s.substring(0,s.length-2)})`},en=(e,t,n)=>n>t?t:n<e?e:n;function ea(e,t){return t?e*(1e3/t):0}const Nm=5;function ta(e,t,n){const s=Math.max(t-Nm,0);return ea(n-e(s),t-s)}const fe={stiffness:100,damping:10,mass:1,velocity:0,duration:800,bounce:.3,visualDuration:.3,restSpeed:{granular:.01,default:2},restDelta:{granular:.005,default:.5},minDuration:.01,maxDuration:10,minDamping:.05,maxDamping:1},sr=.001;function Lm({duration:e=fe.duration,bounce:t=fe.bounce,velocity:n=fe.velocity,mass:s=fe.mass}){let r,i,o=1-t;o=en(fe.minDamping,fe.maxDamping,o),e=en(fe.minDuration,fe.maxDuration,Ct(e)),o<1?(r=d=>{const p=d*o,f=p*e,b=p-n,w=hr(d,o),h=Math.exp(-f);return sr-b/w*h},i=d=>{const f=d*o*e,b=f*n+n,w=Math.pow(o,2)*Math.pow(d,2)*e,h=Math.exp(-f),_=hr(Math.pow(d,2),o);return(-r(d)+sr>0?-1:1)*((b-w)*h)/_}):(r=d=>{const p=Math.exp(-d*e),f=(d-n)*e+1;return-sr+p*f},i=d=>{const p=Math.exp(-d*e),f=(n-d)*(e*e);return p*f});const c=5/e,l=jm(r,i,c);if(e=It(e),isNaN(l))return{stiffness:fe.stiffness,damping:fe.damping,duration:e};{const d=Math.pow(l,2)*s;return{stiffness:d,damping:o*2*Math.sqrt(s*d),duration:e}}}const Dm=12;function jm(e,t,n){let s=n;for(let r=1;r<Dm;r++)s=s-e(s)/t(s);return s}function hr(e,t){return e*Math.sqrt(1-t*t)}const qm=["duration","bounce"],Vm=["stiffness","damping","mass"];function Ni(e,t){return t.some(n=>e[n]!==void 0)}function Fm(e){let t={velocity:fe.velocity,stiffness:fe.stiffness,damping:fe.damping,mass:fe.mass,isResolvedFromDuration:!1,...e};if(!Ni(e,Vm)&&Ni(e,qm))if(e.visualDuration){const n=e.visualDuration,s=2*Math.PI/(n*1.2),r=s*s,i=2*en(.05,1,1-(e.bounce||0))*Math.sqrt(r);t={...t,mass:fe.mass,stiffness:r,damping:i}}else{const n=Lm(e);t={...t,...n,mass:fe.mass},t.isResolvedFromDuration=!0}return t}function jr(e=fe.visualDuration,t=fe.bounce){const n=typeof e!="object"?{visualDuration:e,keyframes:[0,1],bounce:t}:e;let{restSpeed:s,restDelta:r}=n;const i=n.keyframes[0],o=n.keyframes[n.keyframes.length-1],c={done:!1,value:i},{stiffness:l,damping:d,mass:p,duration:f,velocity:b,isResolvedFromDuration:w}=Fm({...n,velocity:-Ct(n.velocity||0)}),h=b||0,_=d/(2*Math.sqrt(l*p)),A=o-i,$=Ct(Math.sqrt(l/p)),O=Math.abs(A)<5;s||(s=O?fe.restSpeed.granular:fe.restSpeed.default),r||(r=O?fe.restDelta.granular:fe.restDelta.default);let V;if(_<1){const S=hr($,_);V=M=>{const C=Math.exp(-_*$*M);return o-C*((h+_*$*A)/S*Math.sin(S*M)+A*Math.cos(S*M))}}else if(_===1)V=S=>o-Math.exp(-$*S)*(A+(h+$*A)*S);else{const S=$*Math.sqrt(_*_-1);V=M=>{const C=Math.exp(-_*$*M),I=Math.min(S*M,300);return o-C*((h+_*$*A)*Math.sinh(I)+S*A*Math.cosh(I))/S}}const T={calculatedDuration:w&&f||null,next:S=>{const M=V(S);if(w)c.done=S>=f;else{let C=0;_<1&&(C=S===0?It(h):ta(V,S,M));const I=Math.abs(C)<=s,L=Math.abs(o-M)<=r;c.done=I&&L}return c.value=c.done?o:M,c},toString:()=>{const S=Math.min(Dr(T),Ts),M=Qo(C=>T.next(S*C).value,S,30);return S+"ms "+M}};return T}function Um(e,t=100,n){const s=n({...e,keyframes:[0,t]}),r=Math.min(Dr(s),Ts);return{type:"keyframes",ease:i=>s.next(r*i).value/t,duration:Ct(r)}}function qs(e){return typeof e=="function"}const Zm=(e,t,n)=>{const s=t-e;return((n-e)%s+s)%s+e},na=e=>Array.isArray(e)&&typeof e[0]!="number";function sa(e,t){return na(e)?e[Zm(0,e.length,t)]:e}const Hn=(e,t,n)=>e+(t-e)*n;function ra(e,t){const n=e[e.length-1];for(let s=1;s<=t;s++){const r=js(0,t,s);e.push(Hn(n,1,r))}}function ia(e){const t=[0];return ra(t,e.length-1),t}const je=e=>!!(e&&e.getVelocity);function Hm(e,t,n){var s;if(e instanceof Element)return[e];if(typeof e=="string"){let r=document;const i=(s=n?.[e])!==null&&s!==void 0?s:r.querySelectorAll(e);return i?Array.from(i):[]}return Array.from(e)}function qr(e){return typeof e=="object"&&!Array.isArray(e)}function oa(e,t,n,s){return typeof e=="string"&&qr(t)?Hm(e,n,s):e instanceof NodeList?Array.from(e):Array.isArray(e)?e:[e]}function Bm(e,t,n){return e*(t+1)}function Li(e,t,n,s){var r;return typeof t=="number"?t:t.startsWith("-")||t.startsWith("+")?Math.max(0,e+parseFloat(t)):t==="<"?n:(r=s.get(t))!==null&&r!==void 0?r:e}function Jm(e,t){e.indexOf(t)===-1&&e.push(t)}function aa(e,t){const n=e.indexOf(t);n>-1&&e.splice(n,1)}function Km(e,t,n){for(let s=0;s<e.length;s++){const r=e[s];r.at>t&&r.at<n&&(aa(e,r),s--)}}function Wm(e,t,n,s,r,i){Km(e,r,i);for(let o=0;o<t.length;o++)e.push({value:t[o],at:Hn(r,i,s[o]),easing:sa(n,o)})}function Gm(e,t){for(let n=0;n<e.length;n++)e[n]=e[n]/(t+1)}function Xm(e,t){return e.at===t.at?e.value===null?1:t.value===null?-1:0:e.at-t.at}const Ym="easeInOut";function Qm(e,{defaultTransition:t={},...n}={},s,r){const i=t.duration||.3,o=new Map,c=new Map,l={},d=new Map;let p=0,f=0,b=0;for(let w=0;w<e.length;w++){const h=e[w];if(typeof h=="string"){d.set(h,f);continue}else if(!Array.isArray(h)){d.set(h.name,Li(f,h.at,p,d));continue}let[_,A,$={}]=h;$.at!==void 0&&(f=Li(f,$.at,p,d));let O=0;const V=(T,S,M,C=0,I=0)=>{const L=ef(T),{delay:P=0,times:K=ia(L),type:se="keyframes",repeat:G,repeatType:gt,repeatDelay:St=0,...he}=S;let{ease:ue=t.ease||"easeOut",duration:ie}=S;const _e=typeof P=="function"?P(C,I):P,pe=L.length,He=qs(se)?se:r?.[se];if(pe<=2&&He){let $e=100;if(pe===2&&sf(L)){const qe=L[1]-L[0];$e=Math.abs(qe)}const be={...he};ie!==void 0&&(be.duration=It(ie));const Ne=Um(be,$e,He);ue=Ne.ease,ie=Ne.duration}ie??(ie=i);const Se=f+_e;K.length===1&&K[0]===0&&(K[1]=1);const xe=K.length-L.length;if(xe>0&&ra(K,xe),L.length===1&&L.unshift(null),G){ie=Bm(ie,G);const $e=[...L],be=[...K];ue=Array.isArray(ue)?[...ue]:[ue];const Ne=[...ue];for(let qe=0;qe<G;qe++){L.push(...$e);for(let Ee=0;Ee<$e.length;Ee++)K.push(be[Ee]+(qe+1)),ue.push(Ee===0?"linear":sa(Ne,Ee-1))}Gm(K,G)}const Ae=Se+ie;Wm(M,L,ue,K,Se,Ae),O=Math.max(_e+ie,O),b=Math.max(Ae,b)};if(je(_)){const T=Di(_,c);V(A,$,ji("default",T))}else{const T=oa(_,A,s,l),S=T.length;for(let M=0;M<S;M++){A=A,$=$;const C=T[M],I=Di(C,c);for(const L in A)V(A[L],tf($,L),ji(L,I),M,S)}}p=f,f+=O}return c.forEach((w,h)=>{for(const _ in w){const A=w[_];A.sort(Xm);const $=[],O=[],V=[];for(let S=0;S<A.length;S++){const{at:M,value:C,easing:I}=A[S];$.push(C),O.push(js(0,b,M)),V.push(I||"easeOut")}O[0]!==0&&(O.unshift(0),$.unshift($[0]),V.unshift(Ym)),O[O.length-1]!==1&&(O.push(1),$.push(null)),o.has(h)||o.set(h,{keyframes:{},transition:{}});const T=o.get(h);T.keyframes[_]=$,T.transition[_]={...t,duration:b,ease:V,times:O,...n}}}),o}function Di(e,t){return!t.has(e)&&t.set(e,{}),t.get(e)}function ji(e,t){return t[e]||(t[e]=[]),t[e]}function ef(e){return Array.isArray(e)?e:[e]}function tf(e,t){return e&&e[t]?{...e,...e[t]}:{...e}}const nf=e=>typeof e=="number",sf=e=>e.every(nf),bn=new WeakMap;function ca(e,t){return e?e[t]||e.default||e:void 0}const xn=["transformPerspective","x","y","z","translateX","translateY","translateZ","scale","scaleX","scaleY","rotate","rotateX","rotateY","rotateZ","skew","skewX","skewY"],$n=new Set(xn),la=new Set(["width","height","top","left","right","bottom",...xn]),rf=e=>Array.isArray(e),of=e=>rf(e)?e[e.length-1]||0:e,af={useManualTiming:!1};function cf(e){let t=new Set,n=new Set,s=!1,r=!1;const i=new WeakSet;let o={delta:0,timestamp:0,isProcessing:!1};function c(d){i.has(d)&&(l.schedule(d),e()),d(o)}const l={schedule:(d,p=!1,f=!1)=>{const w=f&&s?t:n;return p&&i.add(d),w.has(d)||w.add(d),d},cancel:d=>{n.delete(d),i.delete(d)},process:d=>{if(o=d,s){r=!0;return}s=!0,[t,n]=[n,t],t.forEach(c),t.clear(),s=!1,r&&(r=!1,l.process(d))}};return l}const hs=["read","resolveKeyframes","update","preRender","render","postRender"],lf=40;function df(e,t){let n=!1,s=!0;const r={delta:0,timestamp:0,isProcessing:!1},i=()=>n=!0,o=hs.reduce(($,O)=>($[O]=cf(i),$),{}),{read:c,resolveKeyframes:l,update:d,preRender:p,render:f,postRender:b}=o,w=()=>{const $=performance.now();n=!1,r.delta=s?1e3/60:Math.max(Math.min($-r.timestamp,lf),1),r.timestamp=$,r.isProcessing=!0,c.process(r),l.process(r),d.process(r),p.process(r),f.process(r),b.process(r),r.isProcessing=!1,n&&t&&(s=!1,e(w))},h=()=>{n=!0,s=!0,r.isProcessing||e(w)};return{schedule:hs.reduce(($,O)=>{const V=o[O];return $[O]=(T,S=!1,M=!1)=>(n||h(),V.schedule(T,S,M)),$},{}),cancel:$=>{for(let O=0;O<hs.length;O++)o[hs[O]].cancel($)},state:r,steps:o}}const{schedule:Rt,cancel:gr,state:As}=df(typeof requestAnimationFrame<"u"?requestAnimationFrame:Qt,!0);let bs;function uf(){bs=void 0}const Ft={now:()=>(bs===void 0&&Ft.set(As.isProcessing||af.useManualTiming?As.timestamp:performance.now()),bs),set:e=>{bs=e,queueMicrotask(uf)}};class da{constructor(){this.subscriptions=[]}add(t){return Jm(this.subscriptions,t),()=>aa(this.subscriptions,t)}notify(t,n,s){const r=this.subscriptions.length;if(r)if(r===1)this.subscriptions[0](t,n,s);else for(let i=0;i<r;i++){const o=this.subscriptions[i];o&&o(t,n,s)}}getSize(){return this.subscriptions.length}clear(){this.subscriptions.length=0}}const qi=30,pf=e=>!isNaN(parseFloat(e));class mf{constructor(t,n={}){this.version="11.18.2",this.canTrackVelocity=null,this.events={},this.updateAndNotify=(s,r=!0)=>{const i=Ft.now();this.updatedAt!==i&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(s),this.current!==this.prev&&this.events.change&&this.events.change.notify(this.current),r&&this.events.renderRequest&&this.events.renderRequest.notify(this.current)},this.hasAnimated=!1,this.setCurrent(t),this.owner=n.owner}setCurrent(t){this.current=t,this.updatedAt=Ft.now(),this.canTrackVelocity===null&&t!==void 0&&(this.canTrackVelocity=pf(this.current))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new da);const s=this.events[t].add(n);return t==="change"?()=>{s(),Rt.read(()=>{this.events.change.getSize()||this.stop()})}:s}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,n){this.passiveEffect=t,this.stopPassiveEffect=n}set(t,n=!0){!n||!this.passiveEffect?this.updateAndNotify(t,n):this.passiveEffect(t,this.updateAndNotify)}setWithVelocity(t,n,s){this.set(n),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-s}jump(t,n=!0){this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,n&&this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}get(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=Ft.now();if(!this.canTrackVelocity||this.prevFrameValue===void 0||t-this.updatedAt>qi)return 0;const n=Math.min(this.updatedAt-this.prevUpdatedAt,qi);return ea(parseFloat(this.current)-parseFloat(this.prevFrameValue),n)}start(t){return this.stop(),new Promise(n=>{this.hasAnimated=!0,this.animation=t(n),this.events.animationStart&&this.events.animationStart.notify()}).then(()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()})}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function Fn(e,t){return new mf(e,t)}function Vi(e){const t=[{},{}];return e?.values.forEach((n,s)=>{t[0][s]=n.get(),t[1][s]=n.getVelocity()}),t}function ua(e,t,n,s){if(typeof t=="function"){const[r,i]=Vi(s);t=t(n!==void 0?n:e.custom,r,i)}if(typeof t=="string"&&(t=e.variants&&e.variants[t]),typeof t=="function"){const[r,i]=Vi(s);t=t(n!==void 0?n:e.custom,r,i)}return t}function ff(e,t,n){const s=e.getProps();return ua(s,t,s.custom,e)}function hf(e,t,n){e.hasValue(t)?e.getValue(t).set(n):e.addValue(t,Fn(n))}function gf(e,t){const n=ff(e,t);let{transitionEnd:s={},transition:r={},...i}=n||{};i={...i,...s};for(const o in i){const c=of(i[o]);hf(e,o,c)}}function vf(e){return!!(je(e)&&e.add)}function yf(e,t){const n=e.getValue("willChange");if(vf(n))return n.add(t)}const Vr=e=>e.replace(/([a-z])([A-Z])/gu,"$1-$2").toLowerCase(),bf="framerAppearId",wf="data-"+Vr(bf);function _f(e){return e.props[wf]}function Fi(e,t){e.timeline=t,e.onfinish=null}const Fr=e=>Array.isArray(e)&&typeof e[0]=="number",Sf={linearEasing:void 0};function xf(e,t){const n=Lr(e);return()=>{var s;return(s=Sf[t])!==null&&s!==void 0?s:n()}}const Es=xf(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing");function pa(e){return!!(typeof e=="function"&&Es()||!e||typeof e=="string"&&(e in vr||Es())||Fr(e)||Array.isArray(e)&&e.every(pa))}const Ln=([e,t,n,s])=>`cubic-bezier(${e}, ${t}, ${n}, ${s})`,vr={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:Ln([0,.65,.55,1]),circOut:Ln([.55,0,1,.45]),backIn:Ln([.31,.01,.66,-.59]),backOut:Ln([.33,1.53,.69,.99])};function ma(e,t){if(e)return typeof e=="function"&&Es()?Qo(e,t):Fr(e)?Ln(e):Array.isArray(e)?e.map(n=>ma(n,t)||vr.easeOut):vr[e]}const fa=(e,t,n)=>(((1-3*n+3*t)*e+(3*n-6*t))*e+3*t)*e,$f=1e-7,kf=12;function Tf(e,t,n,s,r){let i,o,c=0;do o=t+(n-t)/2,i=fa(o,s,r)-e,i>0?n=o:t=o;while(Math.abs(i)>$f&&++c<kf);return o}function Bn(e,t,n,s){if(e===t&&n===s)return Qt;const r=i=>Tf(i,0,1,e,n);return i=>i===0||i===1?i:fa(r(i),t,s)}const ha=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,ga=e=>t=>1-e(1-t),va=Bn(.33,1.53,.69,.99),Ur=ga(va),ya=ha(Ur),ba=e=>(e*=2)<1?.5*Ur(e):.5*(2-Math.pow(2,-10*(e-1))),Zr=e=>1-Math.sin(Math.acos(e)),Af=ga(Zr),wa=ha(Zr),_a=e=>/^0[^.\s]+$/u.test(e);function Ef(e){return typeof e=="number"?e===0:e!==null?e==="none"||e==="0"||_a(e):!0}const kn={test:e=>typeof e=="number",parse:parseFloat,transform:e=>e},Un={...kn,transform:e=>en(0,1,e)},gs={...kn,default:1},qn=e=>Math.round(e*1e5)/1e5,Hr=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;function If(e){return e==null}const Cf=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,Br=(e,t)=>n=>!!(typeof n=="string"&&Cf.test(n)&&n.startsWith(e)||t&&!If(n)&&Object.prototype.hasOwnProperty.call(n,t)),Sa=(e,t,n)=>s=>{if(typeof s!="string")return s;const[r,i,o,c]=s.match(Hr);return{[e]:parseFloat(r),[t]:parseFloat(i),[n]:parseFloat(o),alpha:c!==void 0?parseFloat(c):1}},Rf=e=>en(0,255,e),rr={...kn,transform:e=>Math.round(Rf(e))},Xt={test:Br("rgb","red"),parse:Sa("red","green","blue"),transform:({red:e,green:t,blue:n,alpha:s=1})=>"rgba("+rr.transform(e)+", "+rr.transform(t)+", "+rr.transform(n)+", "+qn(Un.transform(s))+")"};function Mf(e){let t="",n="",s="",r="";return e.length>5?(t=e.substring(1,3),n=e.substring(3,5),s=e.substring(5,7),r=e.substring(7,9)):(t=e.substring(1,2),n=e.substring(2,3),s=e.substring(3,4),r=e.substring(4,5),t+=t,n+=n,s+=s,r+=r),{red:parseInt(t,16),green:parseInt(n,16),blue:parseInt(s,16),alpha:r?parseInt(r,16)/255:1}}const yr={test:Br("#"),parse:Mf,transform:Xt.transform},Jn=e=>({test:t=>typeof t=="string"&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),Vt=Jn("deg"),vn=Jn("%"),B=Jn("px"),Pf=Jn("vh"),zf=Jn("vw"),Ui={...vn,parse:e=>vn.parse(e)/100,transform:e=>vn.transform(e*100)},hn={test:Br("hsl","hue"),parse:Sa("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:n,alpha:s=1})=>"hsla("+Math.round(e)+", "+vn.transform(qn(t))+", "+vn.transform(qn(n))+", "+qn(Un.transform(s))+")"},ze={test:e=>Xt.test(e)||yr.test(e)||hn.test(e),parse:e=>Xt.test(e)?Xt.parse(e):hn.test(e)?hn.parse(e):yr.parse(e),transform:e=>typeof e=="string"?e:e.hasOwnProperty("red")?Xt.transform(e):hn.transform(e)},Of=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;function Nf(e){var t,n;return isNaN(e)&&typeof e=="string"&&(((t=e.match(Hr))===null||t===void 0?void 0:t.length)||0)+(((n=e.match(Of))===null||n===void 0?void 0:n.length)||0)>0}const xa="number",$a="color",Lf="var",Df="var(",Zi="${}",jf=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;function Zn(e){const t=e.toString(),n=[],s={color:[],number:[],var:[]},r=[];let i=0;const c=t.replace(jf,l=>(ze.test(l)?(s.color.push(i),r.push($a),n.push(ze.parse(l))):l.startsWith(Df)?(s.var.push(i),r.push(Lf),n.push(l)):(s.number.push(i),r.push(xa),n.push(parseFloat(l))),++i,Zi)).split(Zi);return{values:n,split:c,indexes:s,types:r}}function ka(e){return Zn(e).values}function Ta(e){const{split:t,types:n}=Zn(e),s=t.length;return r=>{let i="";for(let o=0;o<s;o++)if(i+=t[o],r[o]!==void 0){const c=n[o];c===xa?i+=qn(r[o]):c===$a?i+=ze.transform(r[o]):i+=r[o]}return i}}const qf=e=>typeof e=="number"?0:e;function Vf(e){const t=ka(e);return Ta(e)(t.map(qf))}const Tn={test:Nf,parse:ka,createTransformer:Ta,getAnimatableNone:Vf},Ff=new Set(["brightness","contrast","saturate","opacity"]);function Uf(e){const[t,n]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[s]=n.match(Hr)||[];if(!s)return e;const r=n.replace(s,"");let i=Ff.has(t)?1:0;return s!==n&&(i*=100),t+"("+i+r+")"}const Zf=/\b([a-z-]*)\(.*?\)/gu,br={...Tn,getAnimatableNone:e=>{const t=e.match(Zf);return t?t.map(Uf).join(" "):e}},Hf={borderWidth:B,borderTopWidth:B,borderRightWidth:B,borderBottomWidth:B,borderLeftWidth:B,borderRadius:B,radius:B,borderTopLeftRadius:B,borderTopRightRadius:B,borderBottomRightRadius:B,borderBottomLeftRadius:B,width:B,maxWidth:B,height:B,maxHeight:B,top:B,right:B,bottom:B,left:B,padding:B,paddingTop:B,paddingRight:B,paddingBottom:B,paddingLeft:B,margin:B,marginTop:B,marginRight:B,marginBottom:B,marginLeft:B,backgroundPositionX:B,backgroundPositionY:B},Bf={rotate:Vt,rotateX:Vt,rotateY:Vt,rotateZ:Vt,scale:gs,scaleX:gs,scaleY:gs,scaleZ:gs,skew:Vt,skewX:Vt,skewY:Vt,distance:B,translateX:B,translateY:B,translateZ:B,x:B,y:B,z:B,perspective:B,transformPerspective:B,opacity:Un,originX:Ui,originY:Ui,originZ:B},Hi={...kn,transform:Math.round},Jr={...Hf,...Bf,zIndex:Hi,size:B,fillOpacity:Un,strokeOpacity:Un,numOctaves:Hi},Jf={...Jr,color:ze,backgroundColor:ze,outlineColor:ze,fill:ze,stroke:ze,borderColor:ze,borderTopColor:ze,borderRightColor:ze,borderBottomColor:ze,borderLeftColor:ze,filter:br,WebkitFilter:br},Kr=e=>Jf[e];function Aa(e,t){let n=Kr(e);return n!==br&&(n=Tn),n.getAnimatableNone?n.getAnimatableNone(t):void 0}const Kf=new Set(["auto","none","0"]);function Wf(e,t,n){let s=0,r;for(;s<e.length&&!r;){const i=e[s];typeof i=="string"&&!Kf.has(i)&&Zn(i).values.length&&(r=e[s]),s++}if(r&&n)for(const i of t)e[i]=Aa(n,r)}const Bi=e=>e===kn||e===B,Ji=(e,t)=>parseFloat(e.split(", ")[t]),Ki=(e,t)=>(n,{transform:s})=>{if(s==="none"||!s)return 0;const r=s.match(/^matrix3d\((.+)\)$/u);if(r)return Ji(r[1],t);{const i=s.match(/^matrix\((.+)\)$/u);return i?Ji(i[1],e):0}},Gf=new Set(["x","y","z"]),Xf=xn.filter(e=>!Gf.has(e));function Yf(e){const t=[];return Xf.forEach(n=>{const s=e.getValue(n);s!==void 0&&(t.push([n,s.get()]),s.set(n.startsWith("scale")?1:0))}),t}const wn={width:({x:e},{paddingLeft:t="0",paddingRight:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),height:({y:e},{paddingTop:t="0",paddingBottom:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),top:(e,{top:t})=>parseFloat(t),left:(e,{left:t})=>parseFloat(t),bottom:({y:e},{top:t})=>parseFloat(t)+(e.max-e.min),right:({x:e},{left:t})=>parseFloat(t)+(e.max-e.min),x:Ki(4,13),y:Ki(5,14)};wn.translateX=wn.x;wn.translateY=wn.y;const Yt=new Set;let wr=!1,_r=!1;function Ea(){if(_r){const e=Array.from(Yt).filter(s=>s.needsMeasurement),t=new Set(e.map(s=>s.element)),n=new Map;t.forEach(s=>{const r=Yf(s);r.length&&(n.set(s,r),s.render())}),e.forEach(s=>s.measureInitialState()),t.forEach(s=>{s.render();const r=n.get(s);r&&r.forEach(([i,o])=>{var c;(c=s.getValue(i))===null||c===void 0||c.set(o)})}),e.forEach(s=>s.measureEndState()),e.forEach(s=>{s.suspendedScrollY!==void 0&&window.scrollTo(0,s.suspendedScrollY)})}_r=!1,wr=!1,Yt.forEach(e=>e.complete()),Yt.clear()}function Ia(){Yt.forEach(e=>{e.readKeyframes(),e.needsMeasurement&&(_r=!0)})}function Qf(){Ia(),Ea()}class Wr{constructor(t,n,s,r,i,o=!1){this.isComplete=!1,this.isAsync=!1,this.needsMeasurement=!1,this.isScheduled=!1,this.unresolvedKeyframes=[...t],this.onComplete=n,this.name=s,this.motionValue=r,this.element=i,this.isAsync=o}scheduleResolve(){this.isScheduled=!0,this.isAsync?(Yt.add(this),wr||(wr=!0,Rt.read(Ia),Rt.resolveKeyframes(Ea))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:n,element:s,motionValue:r}=this;for(let i=0;i<t.length;i++)if(t[i]===null)if(i===0){const o=r?.get(),c=t[t.length-1];if(o!==void 0)t[0]=o;else if(s&&n){const l=s.readValue(n,c);l!=null&&(t[0]=l)}t[0]===void 0&&(t[0]=c),r&&o===void 0&&r.set(t[0])}else t[i]=t[i-1]}setFinalKeyframe(){}measureInitialState(){}renderEndStyles(){}measureEndState(){}complete(){this.isComplete=!0,this.onComplete(this.unresolvedKeyframes,this.finalKeyframe),Yt.delete(this)}cancel(){this.isComplete||(this.isScheduled=!1,Yt.delete(this))}resume(){this.isComplete||this.scheduleResolve()}}const Ca=e=>/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(e),Ra=e=>t=>typeof t=="string"&&t.startsWith(e),Ma=Ra("--"),eh=Ra("var(--"),Gr=e=>eh(e)?th.test(e.split("/*")[0].trim()):!1,th=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu,nh=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function sh(e){const t=nh.exec(e);if(!t)return[,];const[,n,s,r]=t;return[`--${n??s}`,r]}function Pa(e,t,n=1){const[s,r]=sh(e);if(!s)return;const i=window.getComputedStyle(t).getPropertyValue(s);if(i){const o=i.trim();return Ca(o)?parseFloat(o):o}return Gr(r)?Pa(r,t,n+1):r}const za=e=>t=>t.test(e),rh={test:e=>e==="auto",parse:e=>e},Oa=[kn,B,vn,Vt,zf,Pf,rh],Wi=e=>Oa.find(za(e));class Na extends Wr{constructor(t,n,s,r,i){super(t,n,s,r,i,!0)}readKeyframes(){const{unresolvedKeyframes:t,element:n,name:s}=this;if(!n||!n.current)return;super.readKeyframes();for(let l=0;l<t.length;l++){let d=t[l];if(typeof d=="string"&&(d=d.trim(),Gr(d))){const p=Pa(d,n.current);p!==void 0&&(t[l]=p),l===t.length-1&&(this.finalKeyframe=d)}}if(this.resolveNoneKeyframes(),!la.has(s)||t.length!==2)return;const[r,i]=t,o=Wi(r),c=Wi(i);if(o!==c)if(Bi(o)&&Bi(c))for(let l=0;l<t.length;l++){const d=t[l];typeof d=="string"&&(t[l]=parseFloat(d))}else this.needsMeasurement=!0}resolveNoneKeyframes(){const{unresolvedKeyframes:t,name:n}=this,s=[];for(let r=0;r<t.length;r++)Ef(t[r])&&s.push(r);s.length&&Wf(t,s,n)}measureInitialState(){const{element:t,unresolvedKeyframes:n,name:s}=this;if(!t||!t.current)return;s==="height"&&(this.suspendedScrollY=window.pageYOffset),this.measuredOrigin=wn[s](t.measureViewportBox(),window.getComputedStyle(t.current)),n[0]=this.measuredOrigin;const r=n[n.length-1];r!==void 0&&t.getValue(s,r).jump(r,!1)}measureEndState(){var t;const{element:n,name:s,unresolvedKeyframes:r}=this;if(!n||!n.current)return;const i=n.getValue(s);i&&i.jump(this.measuredOrigin,!1);const o=r.length-1,c=r[o];r[o]=wn[s](n.measureViewportBox(),window.getComputedStyle(n.current)),c!==null&&this.finalKeyframe===void 0&&(this.finalKeyframe=c),!((t=this.removedTransforms)===null||t===void 0)&&t.length&&this.removedTransforms.forEach(([l,d])=>{n.getValue(l).set(d)}),this.resolveNoneKeyframes()}}const Gi=(e,t)=>t==="zIndex"?!1:!!(typeof e=="number"||Array.isArray(e)||typeof e=="string"&&(Tn.test(e)||e==="0")&&!e.startsWith("url("));function ih(e){const t=e[0];if(e.length===1)return!0;for(let n=0;n<e.length;n++)if(e[n]!==t)return!0}function oh(e,t,n,s){const r=e[0];if(r===null)return!1;if(t==="display"||t==="visibility")return!0;const i=e[e.length-1],o=Gi(r,t),c=Gi(i,t);return!o||!c?!1:ih(e)||(n==="spring"||qs(n))&&s}const ah=e=>e!==null;function Vs(e,{repeat:t,repeatType:n="loop"},s){const r=e.filter(ah),i=t&&n!=="loop"&&t%2===1?0:r.length-1;return!i||s===void 0?r[i]:s}const ch=40;class La{constructor({autoplay:t=!0,delay:n=0,type:s="keyframes",repeat:r=0,repeatDelay:i=0,repeatType:o="loop",...c}){this.isStopped=!1,this.hasAttemptedResolve=!1,this.createdAt=Ft.now(),this.options={autoplay:t,delay:n,type:s,repeat:r,repeatDelay:i,repeatType:o,...c},this.updateFinishedPromise()}calcStartTime(){return this.resolvedAt?this.resolvedAt-this.createdAt>ch?this.resolvedAt:this.createdAt:this.createdAt}get resolved(){return!this._resolved&&!this.hasAttemptedResolve&&Qf(),this._resolved}onKeyframesResolved(t,n){this.resolvedAt=Ft.now(),this.hasAttemptedResolve=!0;const{name:s,type:r,velocity:i,delay:o,onComplete:c,onUpdate:l,isGenerator:d}=this.options;if(!d&&!oh(t,s,r,i))if(o)this.options.duration=0;else{l&&l(Vs(t,this.options,n)),c&&c(),this.resolveFinishedPromise();return}const p=this.initPlayback(t,n);p!==!1&&(this._resolved={keyframes:t,finalKeyframe:n,...p},this.onPostResolved())}onPostResolved(){}then(t,n){return this.currentFinishedPromise.then(t,n)}flatten(){this.options.type="keyframes",this.options.ease="linear"}updateFinishedPromise(){this.currentFinishedPromise=new Promise(t=>{this.resolveFinishedPromise=t})}}function ir(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function lh({hue:e,saturation:t,lightness:n,alpha:s}){e/=360,t/=100,n/=100;let r=0,i=0,o=0;if(!t)r=i=o=n;else{const c=n<.5?n*(1+t):n+t-n*t,l=2*n-c;r=ir(l,c,e+1/3),i=ir(l,c,e),o=ir(l,c,e-1/3)}return{red:Math.round(r*255),green:Math.round(i*255),blue:Math.round(o*255),alpha:s}}function Is(e,t){return n=>n>0?t:e}const or=(e,t,n)=>{const s=e*e,r=n*(t*t-s)+s;return r<0?0:Math.sqrt(r)},dh=[yr,Xt,hn],uh=e=>dh.find(t=>t.test(e));function Xi(e){const t=uh(e);if(!t)return!1;let n=t.parse(e);return t===hn&&(n=lh(n)),n}const Yi=(e,t)=>{const n=Xi(e),s=Xi(t);if(!n||!s)return Is(e,t);const r={...n};return i=>(r.red=or(n.red,s.red,i),r.green=or(n.green,s.green,i),r.blue=or(n.blue,s.blue,i),r.alpha=Hn(n.alpha,s.alpha,i),Xt.transform(r))},ph=(e,t)=>n=>t(e(n)),Xr=(...e)=>e.reduce(ph),Sr=new Set(["none","hidden"]);function mh(e,t){return Sr.has(e)?n=>n<=0?e:t:n=>n>=1?t:e}function fh(e,t){return n=>Hn(e,t,n)}function Yr(e){return typeof e=="number"?fh:typeof e=="string"?Gr(e)?Is:ze.test(e)?Yi:vh:Array.isArray(e)?Da:typeof e=="object"?ze.test(e)?Yi:hh:Is}function Da(e,t){const n=[...e],s=n.length,r=e.map((i,o)=>Yr(i)(i,t[o]));return i=>{for(let o=0;o<s;o++)n[o]=r[o](i);return n}}function hh(e,t){const n={...e,...t},s={};for(const r in n)e[r]!==void 0&&t[r]!==void 0&&(s[r]=Yr(e[r])(e[r],t[r]));return r=>{for(const i in s)n[i]=s[i](r);return n}}function gh(e,t){var n;const s=[],r={color:0,var:0,number:0};for(let i=0;i<t.values.length;i++){const o=t.types[i],c=e.indexes[o][r[o]],l=(n=e.values[c])!==null&&n!==void 0?n:0;s[i]=l,r[o]++}return s}const vh=(e,t)=>{const n=Tn.createTransformer(t),s=Zn(e),r=Zn(t);return s.indexes.var.length===r.indexes.var.length&&s.indexes.color.length===r.indexes.color.length&&s.indexes.number.length>=r.indexes.number.length?Sr.has(e)&&!r.values.length||Sr.has(t)&&!s.values.length?mh(e,t):Xr(Da(gh(s,r),r.values),n):Is(e,t)};function ja(e,t,n){return typeof e=="number"&&typeof t=="number"&&typeof n=="number"?Hn(e,t,n):Yr(e)(e,t)}function Qi({keyframes:e,velocity:t=0,power:n=.8,timeConstant:s=325,bounceDamping:r=10,bounceStiffness:i=500,modifyTarget:o,min:c,max:l,restDelta:d=.5,restSpeed:p}){const f=e[0],b={done:!1,value:f},w=I=>c!==void 0&&I<c||l!==void 0&&I>l,h=I=>c===void 0?l:l===void 0||Math.abs(c-I)<Math.abs(l-I)?c:l;let _=n*t;const A=f+_,$=o===void 0?A:o(A);$!==A&&(_=$-f);const O=I=>-_*Math.exp(-I/s),V=I=>$+O(I),T=I=>{const L=O(I),P=V(I);b.done=Math.abs(L)<=d,b.value=b.done?$:P};let S,M;const C=I=>{w(b.value)&&(S=I,M=jr({keyframes:[b.value,h(b.value)],velocity:ta(V,I,b.value),damping:r,stiffness:i,restDelta:d,restSpeed:p}))};return C(0),{calculatedDuration:null,next:I=>{let L=!1;return!M&&S===void 0&&(L=!0,T(I),C(I)),S!==void 0&&I>=S?M.next(I-S):(!L&&T(I),b)}}}const yh=Bn(.42,0,1,1),bh=Bn(0,0,.58,1),qa=Bn(.42,0,.58,1),wh={linear:Qt,easeIn:yh,easeInOut:qa,easeOut:bh,circIn:Zr,circInOut:wa,circOut:Af,backIn:Ur,backInOut:ya,backOut:va,anticipate:ba},xr=e=>{if(Fr(e)){Xo(e.length===4);const[t,n,s,r]=e;return Bn(t,n,s,r)}else if(typeof e=="string")return wh[e];return e};function _h(e,t,n){const s=[],r=n||ja,i=e.length-1;for(let o=0;o<i;o++){let c=r(e[o],e[o+1]);if(t){const l=Array.isArray(t)?t[o]||Qt:t;c=Xr(l,c)}s.push(c)}return s}function Sh(e,t,{clamp:n=!0,ease:s,mixer:r}={}){const i=e.length;if(Xo(i===t.length),i===1)return()=>t[0];if(i===2&&t[0]===t[1])return()=>t[1];const o=e[0]===e[1];e[0]>e[i-1]&&(e=[...e].reverse(),t=[...t].reverse());const c=_h(t,s,r),l=c.length,d=p=>{if(o&&p<e[0])return t[0];let f=0;if(l>1)for(;f<e.length-2&&!(p<e[f+1]);f++);const b=js(e[f],e[f+1],p);return c[f](b)};return n?p=>d(en(e[0],e[i-1],p)):d}function xh(e,t){return e.map(n=>n*t)}function $h(e,t){return e.map(()=>t||qa).splice(0,e.length-1)}function Cs({duration:e=300,keyframes:t,times:n,ease:s="easeInOut"}){const r=na(s)?s.map(xr):xr(s),i={done:!1,value:t[0]},o=xh(n&&n.length===t.length?n:ia(t),e),c=Sh(o,t,{ease:Array.isArray(r)?r:$h(t,r)});return{calculatedDuration:e,next:l=>(i.value=c(l),i.done=l>=e,i)}}const kh=e=>{const t=({timestamp:n})=>e(n);return{start:()=>Rt.update(t,!0),stop:()=>gr(t),now:()=>As.isProcessing?As.timestamp:Ft.now()}},Th={decay:Qi,inertia:Qi,tween:Cs,keyframes:Cs,spring:jr},Ah=e=>e/100;class Qr extends La{constructor(t){super(t),this.holdTime=null,this.cancelTime=null,this.currentTime=0,this.playbackSpeed=1,this.pendingPlayState="running",this.startTime=null,this.state="idle",this.stop=()=>{if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.teardown();const{onStop:l}=this.options;l&&l()};const{name:n,motionValue:s,element:r,keyframes:i}=this.options,o=r?.KeyframeResolver||Wr,c=(l,d)=>this.onKeyframesResolved(l,d);this.resolver=new o(i,c,n,s,r),this.resolver.scheduleResolve()}flatten(){super.flatten(),this._resolved&&Object.assign(this._resolved,this.initPlayback(this._resolved.keyframes))}initPlayback(t){const{type:n="keyframes",repeat:s=0,repeatDelay:r=0,repeatType:i,velocity:o=0}=this.options,c=qs(n)?n:Th[n]||Cs;let l,d;c!==Cs&&typeof t[0]!="number"&&(l=Xr(Ah,ja(t[0],t[1])),t=[0,100]);const p=c({...this.options,keyframes:t});i==="mirror"&&(d=c({...this.options,keyframes:[...t].reverse(),velocity:-o})),p.calculatedDuration===null&&(p.calculatedDuration=Dr(p));const{calculatedDuration:f}=p,b=f+r,w=b*(s+1)-r;return{generator:p,mirroredGenerator:d,mapPercentToKeyframes:l,calculatedDuration:f,resolvedDuration:b,totalDuration:w}}onPostResolved(){const{autoplay:t=!0}=this.options;this.play(),this.pendingPlayState==="paused"||!t?this.pause():this.state=this.pendingPlayState}tick(t,n=!1){const{resolved:s}=this;if(!s){const{keyframes:I}=this.options;return{done:!0,value:I[I.length-1]}}const{finalKeyframe:r,generator:i,mirroredGenerator:o,mapPercentToKeyframes:c,keyframes:l,calculatedDuration:d,totalDuration:p,resolvedDuration:f}=s;if(this.startTime===null)return i.next(0);const{delay:b,repeat:w,repeatType:h,repeatDelay:_,onUpdate:A}=this.options;this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-p/this.speed,this.startTime)),n?this.currentTime=t:this.holdTime!==null?this.currentTime=this.holdTime:this.currentTime=Math.round(t-this.startTime)*this.speed;const $=this.currentTime-b*(this.speed>=0?1:-1),O=this.speed>=0?$<0:$>p;this.currentTime=Math.max($,0),this.state==="finished"&&this.holdTime===null&&(this.currentTime=p);let V=this.currentTime,T=i;if(w){const I=Math.min(this.currentTime,p)/f;let L=Math.floor(I),P=I%1;!P&&I>=1&&(P=1),P===1&&L--,L=Math.min(L,w+1),L%2&&(h==="reverse"?(P=1-P,_&&(P-=_/f)):h==="mirror"&&(T=o)),V=en(0,1,P)*f}const S=O?{done:!1,value:l[0]}:T.next(V);c&&(S.value=c(S.value));let{done:M}=S;!O&&d!==null&&(M=this.speed>=0?this.currentTime>=p:this.currentTime<=0);const C=this.holdTime===null&&(this.state==="finished"||this.state==="running"&&M);return C&&r!==void 0&&(S.value=Vs(l,this.options,r)),A&&A(S.value),C&&this.finish(),S}get duration(){const{resolved:t}=this;return t?Ct(t.calculatedDuration):0}get time(){return Ct(this.currentTime)}set time(t){t=It(t),this.currentTime=t,this.holdTime!==null||this.speed===0?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.speed)}get speed(){return this.playbackSpeed}set speed(t){const n=this.playbackSpeed!==t;this.playbackSpeed=t,n&&(this.time=Ct(this.currentTime))}play(){if(this.resolver.isScheduled||this.resolver.resume(),!this._resolved){this.pendingPlayState="running";return}if(this.isStopped)return;const{driver:t=kh,onPlay:n,startTime:s}=this.options;this.driver||(this.driver=t(i=>this.tick(i))),n&&n();const r=this.driver.now();this.holdTime!==null?this.startTime=r-this.holdTime:this.startTime?this.state==="finished"&&(this.startTime=r):this.startTime=s??this.calcStartTime(),this.state==="finished"&&this.updateFinishedPromise(),this.cancelTime=this.startTime,this.holdTime=null,this.state="running",this.driver.start()}pause(){var t;if(!this._resolved){this.pendingPlayState="paused";return}this.state="paused",this.holdTime=(t=this.currentTime)!==null&&t!==void 0?t:0}complete(){this.state!=="running"&&this.play(),this.pendingPlayState=this.state="finished",this.holdTime=null}finish(){this.teardown(),this.state="finished";const{onComplete:t}=this.options;t&&t()}cancel(){this.cancelTime!==null&&this.tick(this.cancelTime),this.teardown(),this.updateFinishedPromise()}teardown(){this.state="idle",this.stopDriver(),this.resolveFinishedPromise(),this.updateFinishedPromise(),this.startTime=this.cancelTime=null,this.resolver.cancel()}stopDriver(){this.driver&&(this.driver.stop(),this.driver=void 0)}sample(t){return this.startTime=0,this.tick(t,!0)}}const Eh=new Set(["opacity","clipPath","filter","transform"]);function Ih(e,t,n,{delay:s=0,duration:r=300,repeat:i=0,repeatType:o="loop",ease:c="easeInOut",times:l}={}){const d={[t]:n};l&&(d.offset=l);const p=ma(c,r);return Array.isArray(p)&&(d.easing=p),e.animate(d,{delay:s,duration:r,easing:Array.isArray(p)?"linear":p,fill:"both",iterations:i+1,direction:o==="reverse"?"alternate":"normal"})}const Ch=Lr(()=>Object.hasOwnProperty.call(Element.prototype,"animate")),Rs=10,Rh=2e4;function Mh(e){return qs(e.type)||e.type==="spring"||!pa(e.ease)}function Ph(e,t){const n=new Qr({...t,keyframes:e,repeat:0,delay:0,isGenerator:!0});let s={done:!1,value:e[0]};const r=[];let i=0;for(;!s.done&&i<Rh;)s=n.sample(i),r.push(s.value),i+=Rs;return{times:void 0,keyframes:r,duration:i-Rs,ease:"linear"}}const Va={anticipate:ba,backInOut:ya,circInOut:wa};function zh(e){return e in Va}class eo extends La{constructor(t){super(t);const{name:n,motionValue:s,element:r,keyframes:i}=this.options;this.resolver=new Na(i,(o,c)=>this.onKeyframesResolved(o,c),n,s,r),this.resolver.scheduleResolve()}initPlayback(t,n){let{duration:s=300,times:r,ease:i,type:o,motionValue:c,name:l,startTime:d}=this.options;if(!c.owner||!c.owner.current)return!1;if(typeof i=="string"&&Es()&&zh(i)&&(i=Va[i]),Mh(this.options)){const{onComplete:f,onUpdate:b,motionValue:w,element:h,..._}=this.options,A=Ph(t,_);t=A.keyframes,t.length===1&&(t[1]=t[0]),s=A.duration,r=A.times,i=A.ease,o="keyframes"}const p=Ih(c.owner.current,l,t,{...this.options,duration:s,times:r,ease:i});return p.startTime=d??this.calcStartTime(),this.pendingTimeline?(Fi(p,this.pendingTimeline),this.pendingTimeline=void 0):p.onfinish=()=>{const{onComplete:f}=this.options;c.set(Vs(t,this.options,n)),f&&f(),this.cancel(),this.resolveFinishedPromise()},{animation:p,duration:s,times:r,type:o,ease:i,keyframes:t}}get duration(){const{resolved:t}=this;if(!t)return 0;const{duration:n}=t;return Ct(n)}get time(){const{resolved:t}=this;if(!t)return 0;const{animation:n}=t;return Ct(n.currentTime||0)}set time(t){const{resolved:n}=this;if(!n)return;const{animation:s}=n;s.currentTime=It(t)}get speed(){const{resolved:t}=this;if(!t)return 1;const{animation:n}=t;return n.playbackRate}set speed(t){const{resolved:n}=this;if(!n)return;const{animation:s}=n;s.playbackRate=t}get state(){const{resolved:t}=this;if(!t)return"idle";const{animation:n}=t;return n.playState}get startTime(){const{resolved:t}=this;if(!t)return null;const{animation:n}=t;return n.startTime}attachTimeline(t){if(!this._resolved)this.pendingTimeline=t;else{const{resolved:n}=this;if(!n)return Qt;const{animation:s}=n;Fi(s,t)}return Qt}play(){if(this.isStopped)return;const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.playState==="finished"&&this.updateFinishedPromise(),n.play()}pause(){const{resolved:t}=this;if(!t)return;const{animation:n}=t;n.pause()}stop(){if(this.resolver.cancel(),this.isStopped=!0,this.state==="idle")return;this.resolveFinishedPromise(),this.updateFinishedPromise();const{resolved:t}=this;if(!t)return;const{animation:n,keyframes:s,duration:r,type:i,ease:o,times:c}=t;if(n.playState==="idle"||n.playState==="finished")return;if(this.time){const{motionValue:d,onUpdate:p,onComplete:f,element:b,...w}=this.options,h=new Qr({...w,keyframes:s,duration:r,type:i,ease:o,times:c,isGenerator:!0}),_=It(this.time);d.setWithVelocity(h.sample(_-Rs).value,h.sample(_).value,Rs)}const{onStop:l}=this.options;l&&l(),this.cancel()}complete(){const{resolved:t}=this;t&&t.animation.finish()}cancel(){const{resolved:t}=this;t&&t.animation.cancel()}static supports(t){const{motionValue:n,name:s,repeatDelay:r,repeatType:i,damping:o,type:c}=t;if(!n||!n.owner||!(n.owner.current instanceof HTMLElement))return!1;const{onUpdate:l,transformTemplate:d}=n.owner.getProps();return Ch()&&s&&Eh.has(s)&&!l&&!d&&!r&&i!=="mirror"&&o!==0&&c!=="inertia"}}const Oh={type:"spring",stiffness:500,damping:25,restSpeed:10},Nh=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),Lh={type:"keyframes",duration:.8},Dh={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},jh=(e,{keyframes:t})=>t.length>2?Lh:$n.has(e)?e.startsWith("scale")?Nh(t[1]):Oh:Dh;function qh({when:e,delay:t,delayChildren:n,staggerChildren:s,staggerDirection:r,repeat:i,repeatType:o,repeatDelay:c,from:l,elapsed:d,...p}){return!!Object.keys(p).length}const Fa=(e,t,n,s={},r,i)=>o=>{const c=ca(s,e)||{},l=c.delay||s.delay||0;let{elapsed:d=0}=s;d=d-It(l);let p={keyframes:Array.isArray(n)?n:[null,n],ease:"easeOut",velocity:t.getVelocity(),...c,delay:-d,onUpdate:b=>{t.set(b),c.onUpdate&&c.onUpdate(b)},onComplete:()=>{o(),c.onComplete&&c.onComplete()},name:e,motionValue:t,element:i?void 0:r};qh(c)||(p={...p,...jh(e,p)}),p.duration&&(p.duration=It(p.duration)),p.repeatDelay&&(p.repeatDelay=It(p.repeatDelay)),p.from!==void 0&&(p.keyframes[0]=p.from);let f=!1;if((p.type===!1||p.duration===0&&!p.repeatDelay)&&(p.duration=0,p.delay===0&&(f=!0)),f&&!i&&t.get()!==void 0){const b=Vs(p.keyframes,c);if(b!==void 0)return Rt.update(()=>{p.onUpdate(b),p.onComplete()}),new Yo([])}return!i&&eo.supports(p)?new eo(p):new Qr(p)};function Vh({protectedKeys:e,needsAnimating:t},n){const s=e.hasOwnProperty(n)&&t[n]!==!0;return t[n]=!1,s}function Fh(e,t,{delay:n=0,transitionOverride:s,type:r}={}){var i;let{transition:o=e.getDefaultTransition(),transitionEnd:c,...l}=t;s&&(o=s);const d=[],p=r&&e.animationState&&e.animationState.getState()[r];for(const f in l){const b=e.getValue(f,(i=e.latestValues[f])!==null&&i!==void 0?i:null),w=l[f];if(w===void 0||p&&Vh(p,f))continue;const h={delay:n,...ca(o||{},f)};let _=!1;if(window.MotionHandoffAnimation){const $=_f(e);if($){const O=window.MotionHandoffAnimation($,f,Rt);O!==null&&(h.startTime=O,_=!0)}}yf(e,f),b.start(Fa(f,b,w,e.shouldReduceMotion&&la.has(f)?{type:!1}:h,e,_));const A=b.animation;A&&d.push(A)}return c&&Promise.all(d).then(()=>{Rt.update(()=>{c&&gf(e,c)})}),d}function Uh(e){return e instanceof SVGElement&&e.tagName!=="svg"}const to=()=>({min:0,max:0}),ei=()=>({x:to(),y:to()}),no={animation:["animate","variants","whileHover","whileTap","exit","whileInView","whileFocus","whileDrag"],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]},$r={};for(const e in no)$r[e]={isEnabled:t=>no[e].some(n=>!!t[n])};const Zh=typeof window<"u",kr={current:null},Ua={current:!1};function Hh(){if(Ua.current=!0,!!Zh)if(window.matchMedia){const e=window.matchMedia("(prefers-reduced-motion)"),t=()=>kr.current=e.matches;e.addListener(t),t()}else kr.current=!1}const Bh=[...Oa,ze,Tn],Jh=e=>Bh.find(za(e));function Kh(e){return e!==null&&typeof e=="object"&&typeof e.start=="function"}function Wh(e){return typeof e=="string"||Array.isArray(e)}const Gh=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],Xh=["initial",...Gh];function Za(e){return Kh(e.animate)||Xh.some(t=>Wh(e[t]))}function Yh(e){return!!(Za(e)||e.variants)}function Qh(e,t,n){for(const s in t){const r=t[s],i=n[s];if(je(r))e.addValue(s,r);else if(je(i))e.addValue(s,Fn(r,{owner:e}));else if(i!==r)if(e.hasValue(s)){const o=e.getValue(s);o.liveStyle===!0?o.jump(r):o.hasAnimated||o.set(r)}else{const o=e.getStaticValue(s);e.addValue(s,Fn(o!==void 0?o:r,{owner:e}))}}for(const s in n)t[s]===void 0&&e.removeValue(s);return t}const so=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];class Ha{scrapeMotionValuesFromProps(t,n,s){return{}}constructor({parent:t,props:n,presenceContext:s,reducedMotionConfig:r,blockInitialAnimation:i,visualState:o},c={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.KeyframeResolver=Wr,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const w=Ft.now();this.renderScheduledAt<w&&(this.renderScheduledAt=w,Rt.render(this.render,!1,!0))};const{latestValues:l,renderState:d,onUpdate:p}=o;this.onUpdate=p,this.latestValues=l,this.baseTarget={...l},this.initialValues=n.initial?{...l}:{},this.renderState=d,this.parent=t,this.props=n,this.presenceContext=s,this.depth=t?t.depth+1:0,this.reducedMotionConfig=r,this.options=c,this.blockInitialAnimation=!!i,this.isControllingVariants=Za(n),this.isVariantNode=Yh(n),this.isVariantNode&&(this.variantChildren=new Set),this.manuallyAnimateOnMount=!!(t&&t.current);const{willChange:f,...b}=this.scrapeMotionValuesFromProps(n,{},this);for(const w in b){const h=b[w];l[w]!==void 0&&je(h)&&h.set(l[w],!1)}}mount(t){this.current=t,bn.set(t,this),this.projection&&!this.projection.instance&&this.projection.mount(t),this.parent&&this.isVariantNode&&!this.isControllingVariants&&(this.removeFromVariantTree=this.parent.addVariantChild(this)),this.values.forEach((n,s)=>this.bindToMotionValue(s,n)),Ua.current||Hh(),this.shouldReduceMotion=this.reducedMotionConfig==="never"?!1:this.reducedMotionConfig==="always"?!0:kr.current,this.parent&&this.parent.children.add(this),this.update(this.props,this.presenceContext)}unmount(){bn.delete(this.current),this.projection&&this.projection.unmount(),gr(this.notifyUpdate),gr(this.render),this.valueSubscriptions.forEach(t=>t()),this.valueSubscriptions.clear(),this.removeFromVariantTree&&this.removeFromVariantTree(),this.parent&&this.parent.children.delete(this);for(const t in this.events)this.events[t].clear();for(const t in this.features){const n=this.features[t];n&&(n.unmount(),n.isMounted=!1)}this.current=null}bindToMotionValue(t,n){this.valueSubscriptions.has(t)&&this.valueSubscriptions.get(t)();const s=$n.has(t),r=n.on("change",c=>{this.latestValues[t]=c,this.props.onUpdate&&Rt.preRender(this.notifyUpdate),s&&this.projection&&(this.projection.isTransformDirty=!0)}),i=n.on("renderRequest",this.scheduleRender);let o;window.MotionCheckAppearSync&&(o=window.MotionCheckAppearSync(this,t,n)),this.valueSubscriptions.set(t,()=>{r(),i(),o&&o(),n.owner&&n.stop()})}sortNodePosition(t){return!this.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}updateFeatures(){let t="animation";for(t in $r){const n=$r[t];if(!n)continue;const{isEnabled:s,Feature:r}=n;if(!this.features[t]&&r&&s(this.props)&&(this.features[t]=new r(this)),this.features[t]){const i=this.features[t];i.isMounted?i.update():(i.mount(),i.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):ei()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,n){this.latestValues[t]=n}update(t,n){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=n;for(let s=0;s<so.length;s++){const r=so[s];this.propEventSubscriptions[r]&&(this.propEventSubscriptions[r](),delete this.propEventSubscriptions[r]);const i="on"+r,o=t[i];o&&(this.propEventSubscriptions[r]=this.on(r,o))}this.prevMotionValues=Qh(this,this.scrapeMotionValuesFromProps(t,this.prevProps,this),this.prevMotionValues),this.handleChildMotionValue&&this.handleChildMotionValue(),this.onUpdate&&this.onUpdate(this)}getProps(){return this.props}getVariant(t){return this.props.variants?this.props.variants[t]:void 0}getDefaultTransition(){return this.props.transition}getTransformPagePoint(){return this.props.transformPagePoint}getClosestVariantNode(){return this.isVariantNode?this:this.parent?this.parent.getClosestVariantNode():void 0}addVariantChild(t){const n=this.getClosestVariantNode();if(n)return n.variantChildren&&n.variantChildren.add(t),()=>n.variantChildren.delete(t)}addValue(t,n){const s=this.values.get(t);n!==s&&(s&&this.removeValue(t),this.bindToMotionValue(t,n),this.values.set(t,n),this.latestValues[t]=n.get())}removeValue(t){this.values.delete(t);const n=this.valueSubscriptions.get(t);n&&(n(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,n){if(this.props.values&&this.props.values[t])return this.props.values[t];let s=this.values.get(t);return s===void 0&&n!==void 0&&(s=Fn(n===null?void 0:n,{owner:this}),this.addValue(t,s)),s}readValue(t,n){var s;let r=this.latestValues[t]!==void 0||!this.current?this.latestValues[t]:(s=this.getBaseTargetFromProps(this.props,t))!==null&&s!==void 0?s:this.readValueFromInstance(this.current,t,this.options);return r!=null&&(typeof r=="string"&&(Ca(r)||_a(r))?r=parseFloat(r):!Jh(r)&&Tn.test(n)&&(r=Aa(t,n)),this.setBaseTarget(t,je(r)?r.get():r)),je(r)?r.get():r}setBaseTarget(t,n){this.baseTarget[t]=n}getBaseTarget(t){var n;const{initial:s}=this.props;let r;if(typeof s=="string"||typeof s=="object"){const o=ua(this.props,s,(n=this.presenceContext)===null||n===void 0?void 0:n.custom);o&&(r=o[t])}if(s&&r!==void 0)return r;const i=this.getBaseTargetFromProps(this.props,t);return i!==void 0&&!je(i)?i:this.initialValues[t]!==void 0&&r===void 0?void 0:this.baseTarget[t]}on(t,n){return this.events[t]||(this.events[t]=new da),this.events[t].add(n)}notify(t,...n){this.events[t]&&this.events[t].notify(...n)}}class Ba extends Ha{constructor(){super(...arguments),this.KeyframeResolver=Na}sortInstanceNodePosition(t,n){return t.compareDocumentPosition(n)&2?1:-1}getBaseTargetFromProps(t,n){return t.style?t.style[n]:void 0}removeValueFromRenderState(t,{vars:n,style:s}){delete n[t],delete s[t]}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;je(t)&&(this.childSubscription=t.on("change",n=>{this.current&&(this.current.textContent=`${n}`)}))}}const Ja=(e,t)=>t&&typeof e=="number"?t.transform(e):e,eg={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},tg=xn.length;function ng(e,t,n){let s="",r=!0;for(let i=0;i<tg;i++){const o=xn[i],c=e[o];if(c===void 0)continue;let l=!0;if(typeof c=="number"?l=c===(o.startsWith("scale")?1:0):l=parseFloat(c)===0,!l||n){const d=Ja(c,Jr[o]);if(!l){r=!1;const p=eg[o]||o;s+=`${p}(${d}) `}n&&(t[o]=d)}}return s=s.trim(),n?s=n(t,r?"":s):r&&(s="none"),s}function Ka(e,t,n){const{style:s,vars:r,transformOrigin:i}=e;let o=!1,c=!1;for(const l in t){const d=t[l];if($n.has(l)){o=!0;continue}else if(Ma(l)){r[l]=d;continue}else{const p=Ja(d,Jr[l]);l.startsWith("origin")?(c=!0,i[l]=p):s[l]=p}}if(t.transform||(o||n?s.transform=ng(t,e.transform,n):s.transform&&(s.transform="none")),c){const{originX:l="50%",originY:d="50%",originZ:p=0}=i;s.transformOrigin=`${l} ${d} ${p}`}}const sg={offset:"stroke-dashoffset",array:"stroke-dasharray"},rg={offset:"strokeDashoffset",array:"strokeDasharray"};function ig(e,t,n=1,s=0,r=!0){e.pathLength=1;const i=r?sg:rg;e[i.offset]=B.transform(-s);const o=B.transform(t),c=B.transform(n);e[i.array]=`${o} ${c}`}function ro(e,t,n){return typeof e=="string"?e:B.transform(t+n*e)}function og(e,t,n){const s=ro(t,e.x,e.width),r=ro(n,e.y,e.height);return`${s} ${r}`}function ag(e,{attrX:t,attrY:n,attrScale:s,originX:r,originY:i,pathLength:o,pathSpacing:c=1,pathOffset:l=0,...d},p,f){if(Ka(e,d,f),p){e.style.viewBox&&(e.attrs.viewBox=e.style.viewBox);return}e.attrs=e.style,e.style={};const{attrs:b,style:w,dimensions:h}=e;b.transform&&(h&&(w.transform=b.transform),delete b.transform),h&&(r!==void 0||i!==void 0||w.transform)&&(w.transformOrigin=og(h,r!==void 0?r:.5,i!==void 0?i:.5)),t!==void 0&&(b.x=t),n!==void 0&&(b.y=n),s!==void 0&&(b.scale=s),o!==void 0&&ig(b,o,c,l,!1)}const Wa=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]),cg=e=>typeof e=="string"&&e.toLowerCase()==="svg";function Ga(e,{style:t,vars:n},s,r){Object.assign(e.style,t,r&&r.getProjectionStyles(s));for(const i in n)e.style.setProperty(i,n[i])}function lg(e,t,n,s){Ga(e,t,void 0,s);for(const r in t.attrs)e.setAttribute(Wa.has(r)?r:Vr(r),t.attrs[r])}const dg={};function ug(e,{layout:t,layoutId:n}){return $n.has(e)||e.startsWith("origin")||(t||n!==void 0)&&(!!dg[e]||e==="opacity")}function Xa(e,t,n){var s;const{style:r}=e,i={};for(const o in r)(je(r[o])||t.style&&je(t.style[o])||ug(o,e)||((s=n?.getValue(o))===null||s===void 0?void 0:s.liveStyle)!==void 0)&&(i[o]=r[o]);return i}function pg(e,t,n){const s=Xa(e,t,n);for(const r in e)if(je(e[r])||je(t[r])){const i=xn.indexOf(r)!==-1?"attr"+r.charAt(0).toUpperCase()+r.substring(1):r;s[i]=e[r]}return s}class mg extends Ba{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=ei}getBaseTargetFromProps(t,n){return t[n]}readValueFromInstance(t,n){if($n.has(n)){const s=Kr(n);return s&&s.default||0}return n=Wa.has(n)?n:Vr(n),t.getAttribute(n)}scrapeMotionValuesFromProps(t,n,s){return pg(t,n,s)}build(t,n,s){ag(t,n,this.isSVGTag,s.transformTemplate)}renderInstance(t,n,s,r){lg(t,n,s,r)}mount(t){this.isSVGTag=cg(t.tagName),super.mount(t)}}function fg({top:e,left:t,right:n,bottom:s}){return{x:{min:t,max:n},y:{min:e,max:s}}}function hg(e,t){if(!t)return e;const n=t({x:e.left,y:e.top}),s=t({x:e.right,y:e.bottom});return{top:n.y,left:n.x,bottom:s.y,right:s.x}}function gg(e,t){return fg(hg(e.getBoundingClientRect(),t))}function vg(e){return window.getComputedStyle(e)}class yg extends Ba{constructor(){super(...arguments),this.type="html",this.renderInstance=Ga}readValueFromInstance(t,n){if($n.has(n)){const s=Kr(n);return s&&s.default||0}else{const s=vg(t),r=(Ma(n)?s.getPropertyValue(n):s[n])||0;return typeof r=="string"?r.trim():r}}measureInstanceViewportBox(t,{transformPagePoint:n}){return gg(t,n)}build(t,n,s){Ka(t,n,s.transformTemplate)}scrapeMotionValuesFromProps(t,n,s){return Xa(t,n,s)}}function bg(e,t){return e in t}class wg extends Ha{constructor(){super(...arguments),this.type="object"}readValueFromInstance(t,n){if(bg(n,t)){const s=t[n];if(typeof s=="string"||typeof s=="number")return s}}getBaseTargetFromProps(){}removeValueFromRenderState(t,n){delete n.output[t]}measureInstanceViewportBox(){return ei()}build(t,n){Object.assign(t.output,n)}renderInstance(t,{output:n}){Object.assign(t,n)}sortInstanceNodePosition(){return 0}}function _g(e){const t={presenceContext:null,props:{},visualState:{renderState:{transform:{},transformOrigin:{},style:{},vars:{},attrs:{}},latestValues:{}}},n=Uh(e)?new mg(t):new yg(t);n.mount(e),bn.set(e,n)}function Sg(e){const t={presenceContext:null,props:{},visualState:{renderState:{output:{}},latestValues:{}}},n=new wg(t);n.mount(e),bn.set(e,n)}function xg(e,t,n){const s=je(e)?e:Fn(e);return s.start(Fa("",s,t,n)),s.animation}function $g(e,t){return je(e)||typeof e=="number"||typeof e=="string"&&!qr(t)}function Ya(e,t,n,s){const r=[];if($g(e,t))r.push(xg(e,qr(t)&&t.default||t,n&&(n.default||n)));else{const i=oa(e,t,s),o=i.length;for(let c=0;c<o;c++){const l=i[c],d=l instanceof Element?_g:Sg;bn.has(l)||d(l);const p=bn.get(l),f={...n};"delay"in f&&typeof f.delay=="function"&&(f.delay=f.delay(c,o)),r.push(...Fh(p,{...t,transition:f},{}))}}return r}function kg(e,t,n){const s=[];return Qm(e,t,n,{spring:jr}).forEach(({keyframes:i,transition:o},c)=>{s.push(...Ya(c,i,o))}),s}function Tg(e){return Array.isArray(e)&&e.some(Array.isArray)}function Ag(e){function t(n,s,r){let i=[];return Tg(n)?i=kg(n,s,e):i=Ya(n,s,r,e),new Yo(i)}return t}const Tr=Ag();function Eg(e,t){if(e==="first")return 0;{const n=t-1;return e==="last"?n:n/2}}function Ig(e=.1,{startDelay:t=0,from:n=0,ease:s}={}){return(r,i)=>{const o=typeof n=="number"?n:Eg(n,i),c=Math.abs(o-r);let l=e*c;if(s){const d=i*e;l=xr(s)(l/d)*d}return t+l}}async function Ht(e,t={}){const n=await fetch(e,{...t,credentials:"include",headers:{"content-type":"application/json",...t.headers||{}}});if(!n.ok){const r=await n.text().catch(()=>"");let i=r||`${e} failed (${n.status})`;try{const o=r?JSON.parse(r):null;o?.error&&(i=o.error)}catch{}throw new Error(i)}const s=await n.text();return s?JSON.parse(s):{}}function tt(e){return document.getElementById(e)}function we(e){return String(e||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function Qa(e="dashboard"){return(window.location.hash||`#/${e}`).replace(/^#\//,"").split("?")[0].split("/")[0].trim()||e}function ti(e,t,n="dashboard"){return t.find(s=>s[0]===e)?e:n}function Cg(e){window.location.hash=`#/${e}`}function Rg(e){function t(){let r=tt("toasts");return r||(r=document.createElement("div"),r.id="toasts",r.className="toasts",document.body.appendChild(r)),r}function n(){const r=t();r.innerHTML=e.toasts.map(i=>`<div class="toast toast-${i.kind}">${we(i.text)}</div>`).join("")}function s(r,i){const o=Math.random().toString(36).slice(2);e.toasts.push({id:o,kind:r,text:i}),e.toasts=e.toasts.slice(-4),n(),setTimeout(()=>{e.toasts=e.toasts.filter(c=>c.id!==o),n()},3500)}return{toast:s,renderToasts:n}}const Kn=[["dashboard","Dashboard","home"],["chat","Chat","message-square"],["agents","Automations","clock"],["channels","Channels","message-circle"],["mcp","MCP","link"],["swarm","Swarm (Live)","share-2"],["files","Files","folder-open"],["memory","Memory","database"],["teams","Teams","users"],["feed","Live Feed","radio"],["settings","Settings","settings"]],Mg={openai:{label:"OpenAI",keyUrl:"https://platform.openai.com/api-keys",placeholder:"sk-proj-..."},anthropic:{label:"Anthropic",keyUrl:"https://console.anthropic.com/settings/keys",placeholder:"sk-ant-..."},google:{label:"Google",keyUrl:"https://aistudio.google.com/app/apikey",placeholder:"AIza..."},groq:{label:"Groq",keyUrl:"https://console.groq.com/keys",placeholder:"gsk_..."},mistral:{label:"Mistral",keyUrl:"https://console.mistral.ai/api-keys/",placeholder:"..."},openrouter:{label:"OpenRouter",keyUrl:"https://openrouter.ai/settings/keys",placeholder:"sk-or-v1-..."},ollama:{label:"Ollama",keyUrl:"",placeholder:"No key required"}};function Pg(){return{authed:!1,route:"dashboard",me:null,client:null,needsProviderOnboarding:!1,providerReady:!1,providerDefault:"",providerDefaultModel:"",providerConnected:[],providerError:"",botName:"Tandem",botAvatarUrl:"",controlPanelName:"Tandem Control Panel",currentSessionId:"",chatUploadedFiles:[],filesDir:"uploads",cleanup:[],toasts:[]}}function Le(e,t){try{const n=e();return n&&typeof n.then=="function"?n.catch(()=>t):Promise.resolve(n??t)}catch{return Promise.resolve(t)}}function ht(e,t){return Array.isArray(e)?e:e&&Array.isArray(e[t])?e[t]:[]}function zg(e){const t=String(e||"").toLowerCase();return t?t.includes("done")||t.includes("complete")||t.includes("success")||t.includes("finished")?"completed":t.includes("fail")||t.includes("error")||t.includes("cancel")||t.includes("deny")?"failed":t.includes("wait")||t.includes("queue")||t.includes("new")||t.includes("pending")?"queued":"running":"running"}function io(e){const t=[e?.updatedAtMs,e?.updated_at_ms,e?.finishedAtMs,e?.finished_at_ms,e?.startedAtMs,e?.started_at_ms,e?.createdAtMs,e?.created_at_ms,e?.firedAtMs,e?.fired_at_ms];for(const n of t){const s=Number(n);if(Number.isFinite(s)&&s>0)return s}return 0}function Og(e){const t=[e?.total_tokens,e?.totalTokens];for(const n of t){const s=Number(n);if(Number.isFinite(s)&&s>=0)return s}return 0}function Ng(e){const t=[e?.estimated_cost_usd,e?.estimatedCostUsd];for(const n of t){const s=Number(n);if(Number.isFinite(s)&&s>=0)return s}return 0}function Lg(e){if(!e)return!1;const t=e.schedule||e.cron||e.interval||e.trigger;return typeof t=="string"?t.trim().length>0:typeof t=="number"?t>0:t&&typeof t=="object"?Object.keys(t).length>0:!1}function ar(e){const t=Math.max(1,...e.map(n=>n.value));return e.map(n=>({...n,pct:Math.max(4,Math.round(n.value/t*100))})).filter(n=>n.value>0)}async function Dg(e){const{api:t,state:n,byId:s,escapeHtml:r,setRoute:i}=e,[o,c,l,d,p,f,b,w,h,_,A,$,O,V]=await Promise.all([Le(()=>t("/api/system/health"),{}),Le(()=>n.client.providers.config(),{default:null,providers:{}}),Le(()=>n.client.channels.status(),{}),Le(()=>n.client.routines.list(),{routines:[]}),Le(()=>n.client.automations.list(),{automations:[]}),Le(()=>n.client?.automationsV2?.list?n.client.automationsV2.list():{automations:[]},{automations:[]}),Le(()=>n.client.routines.listRuns({limit:120}),{runs:[]}),Le(()=>n.client.automations.listRuns({limit:120}),{runs:[]}),Le(async()=>{if(!n.client?.automationsV2?.list||!n.client?.automationsV2?.listRuns)return{runs:[]};const F=await n.client.automationsV2.list(),X=ht(F,"automations").slice(0,30);return{runs:(await Promise.all(X.map(Ve=>Le(()=>n.client.automationsV2.listRuns(String(Ve?.automation_id||Ve?.automationId||Ve?.id||""),20),{runs:[]})))).flatMap(Ve=>ht(Ve,"runs"))}},{runs:[]}),Le(()=>n.client.sessions.list({pageSize:50}),[]),Le(()=>t("/api/swarm/status"),{status:"unknown"}),Le(()=>t("/api/swarm/snapshot"),{registry:{value:{tasks:{}}}}),Le(()=>n.client?.agentTeams?.listInstances?n.client.agentTeams.listInstances():{},{instances:[]}),Le(()=>n.client?.agentTeams?.listApprovals?n.client.agentTeams.listApprovals():{},{spawnApprovals:[]})]),T=ht(d,"routines"),S=ht(p,"automations"),M=ht(f,"automations"),C=ht(b,"runs"),I=ht(w,"runs"),L=ht(h,"runs"),P=[...C,...I,...L],K=ht(_,"sessions"),se=ht(O,"instances"),G=ht(V,"spawnApprovals"),gt=Object.values($?.registry?.value?.tasks||{}),St=Object.values(l||{}).filter(F=>F?.connected).length,he={completed:0,running:0,queued:0,failed:0};for(const F of P)he[zg(F?.status)]+=1;const ue=ar([{key:"completed",label:"Completed",value:he.completed},{key:"running",label:"Running",value:he.running},{key:"queued",label:"Queued",value:he.queued},{key:"failed",label:"Failed",value:he.failed}]),ie=[...T,...S,...M],_e=ie.filter(F=>Lg(F)).length,pe=Math.max(ie.length-_e,0),He=ie.filter(F=>{const X=String(F?.status||"").toLowerCase();return X.includes("pause")||X.includes("disable")||X.includes("stop")}).length,Se=ar([{key:"scheduled",label:"Scheduled",value:_e},{key:"manual",label:"Manual",value:pe},{key:"paused",label:"Paused/Disabled",value:He}]),xe={running:0,done:0,failed:0};for(const F of gt){const X=String(F?.status||"").toLowerCase();X.includes("fail")||X.includes("error")?xe.failed+=1:X.includes("done")||X.includes("complete")?xe.done+=1:xe.running+=1}const Ae=ar([{key:"running",label:"Active",value:xe.running},{key:"completed",label:"Completed",value:xe.done},{key:"failed",label:"Failed",value:xe.failed}]),$e=Date.now(),be=new Array(12).fill(0).map((F,X)=>({label:`${11-X}h`,value:0}));for(const F of P){const X=io(F);if(!X)continue;const Re=Math.floor(($e-X)/36e5);Re>=0&&Re<12&&(be[11-Re].value+=1)}const Ne=Math.max(1,...be.map(F=>F.value)),qe=$e-24*36e5,Ee=$e-168*36e5;let vt=0,ke=0,ct=0,yt=0;const Be=new Map;for(const F of P){const X=io(F),Re=Og(F),Mt=Ng(F),Ve=String(F?.automation_id||F?.automationId||F?.automationID||F?.routine_id||F?.routineId||"unknown").trim();if(X>=Ee&&(ke+=Re,yt+=Mt),X>=qe&&(vt+=Re,ct+=Mt),Ve){const lt=Be.get(Ve)||{cost:0,tokens:0,runs:0};lt.cost+=Mt,lt.tokens+=Re,lt.runs+=1,Be.set(Ve,lt)}}const bt=[...Be.entries()].map(([F,X])=>({id:F,...X})).sort((F,X)=>X.cost-F.cost).slice(0,6);s("view").innerHTML=`
|
|
41
|
+
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
42
|
+
<div class="tcp-card">
|
|
43
|
+
<div class="mb-2 flex items-center justify-between"><span class="tcp-subtle">Engine</span><i data-lucide="cpu"></i></div>
|
|
44
|
+
<div class="text-2xl font-semibold">${r(o.engine?.version||"unknown")}</div>
|
|
45
|
+
<p class="mt-1 text-sm ${o.engine?.ready||o.engine?.healthy?"text-lime-300":"text-rose-300"}">${o.engine?.ready||o.engine?.healthy?"Healthy":"Unhealthy"}</p>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="tcp-card">
|
|
48
|
+
<div class="mb-2 flex items-center justify-between"><span class="tcp-subtle">Provider</span><i data-lucide="bot"></i></div>
|
|
49
|
+
<div class="text-2xl font-semibold">${r(c.default||"none")}</div>
|
|
50
|
+
<p class="mt-1 text-sm text-slate-400">Default model configured</p>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="tcp-card">
|
|
53
|
+
<div class="mb-2 flex items-center justify-between"><span class="tcp-subtle">Channels</span><i data-lucide="messages-square"></i></div>
|
|
54
|
+
<div class="text-2xl font-semibold">${St}</div>
|
|
55
|
+
<p class="mt-1 text-sm text-slate-400">Connected integrations</p>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="tcp-card">
|
|
58
|
+
<div class="mb-2 flex items-center justify-between"><span class="tcp-subtle">Scheduled</span><i data-lucide="clock-3"></i></div>
|
|
59
|
+
<div class="text-2xl font-semibold">${_e}</div>
|
|
60
|
+
<p class="mt-1 text-sm text-slate-400">Routines + automations with a trigger</p>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<section class="tcp-card">
|
|
65
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
66
|
+
<h3 class="tcp-title">Automations + Cost</h3>
|
|
67
|
+
<span class="tcp-subtle text-xs">all automation run paths</span>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="dashboard-kpis mb-4">
|
|
70
|
+
<div><span class="dashboard-kpi-label">Tokens (24h)</span><strong>${vt.toLocaleString()}</strong></div>
|
|
71
|
+
<div><span class="dashboard-kpi-label">Tokens (7d)</span><strong>${ke.toLocaleString()}</strong></div>
|
|
72
|
+
<div><span class="dashboard-kpi-label">Estimated Cost (24h)</span><strong>$${ct.toFixed(4)}</strong></div>
|
|
73
|
+
<div><span class="dashboard-kpi-label">Estimated Cost (7d)</span><strong>$${yt.toFixed(4)}</strong></div>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="mb-2 text-xs text-slate-500">
|
|
76
|
+
Cost estimate uses server rate TANDEM_TOKEN_COST_PER_1K_USD and run token totals from provider usage telemetry.
|
|
77
|
+
</div>
|
|
78
|
+
${bt.length?`<div class="dashboard-bars">${bt.map(F=>{const X=yt>0?Math.max(4,Math.round(F.cost/Math.max(yt,1e-4)*100)):4;return`
|
|
79
|
+
<div class="dashboard-bar-row">
|
|
80
|
+
<div class="dashboard-bar-meta">
|
|
81
|
+
<span class="font-mono">${r(F.id)}</span>
|
|
82
|
+
<span class="dashboard-bar-count">$${F.cost.toFixed(4)} · ${F.tokens.toLocaleString()} tok · ${F.runs} runs</span>
|
|
83
|
+
</div>
|
|
84
|
+
<div class="dashboard-bar-track"><span class="dashboard-bar-fill running" style="width:${X}%"></span></div>
|
|
85
|
+
</div>
|
|
86
|
+
`}).join("")}</div>`:'<p class="tcp-subtle">No token/cost telemetry recorded yet for sampled runs.</p>'}
|
|
87
|
+
</section>
|
|
88
|
+
|
|
89
|
+
<div class="grid gap-4 xl:grid-cols-3">
|
|
90
|
+
<section class="tcp-card">
|
|
91
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
92
|
+
<h3 class="tcp-title">Run Status (latest ${P.length})</h3>
|
|
93
|
+
<span class="tcp-subtle text-xs">routines + automations</span>
|
|
94
|
+
</div>
|
|
95
|
+
${ue.length?`<div class="dashboard-bars">${ue.map(F=>`
|
|
96
|
+
<div class="dashboard-bar-row">
|
|
97
|
+
<div class="dashboard-bar-meta">
|
|
98
|
+
<span>${r(F.label)}</span>
|
|
99
|
+
<span class="dashboard-bar-count">${F.value}</span>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="dashboard-bar-track"><span class="dashboard-bar-fill ${F.key}" style="width:${F.pct}%"></span></div>
|
|
102
|
+
</div>
|
|
103
|
+
`).join("")}</div>`:'<p class="tcp-subtle">No run history yet.</p>'}
|
|
104
|
+
</section>
|
|
105
|
+
|
|
106
|
+
<section class="tcp-card">
|
|
107
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
108
|
+
<h3 class="tcp-title">Schedule Composition</h3>
|
|
109
|
+
<span class="tcp-subtle text-xs">${ie.length} configured</span>
|
|
110
|
+
</div>
|
|
111
|
+
${Se.length?`<div class="dashboard-bars">${Se.map(F=>`
|
|
112
|
+
<div class="dashboard-bar-row">
|
|
113
|
+
<div class="dashboard-bar-meta">
|
|
114
|
+
<span>${r(F.label)}</span>
|
|
115
|
+
<span class="dashboard-bar-count">${F.value}</span>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="dashboard-bar-track"><span class="dashboard-bar-fill ${F.key}" style="width:${F.pct}%"></span></div>
|
|
118
|
+
</div>
|
|
119
|
+
`).join("")}</div>`:'<p class="tcp-subtle">No routines or automations found.</p>'}
|
|
120
|
+
</section>
|
|
121
|
+
|
|
122
|
+
<section class="tcp-card">
|
|
123
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
124
|
+
<h3 class="tcp-title">Execution Snapshot</h3>
|
|
125
|
+
<span class="tcp-subtle text-xs">swarm + teams</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="dashboard-kpis mb-3">
|
|
128
|
+
<div><span class="dashboard-kpi-label">Swarm status</span><strong>${r(String(A.status||"unknown"))}</strong></div>
|
|
129
|
+
<div><span class="dashboard-kpi-label">Team instances</span><strong>${se.length}</strong></div>
|
|
130
|
+
<div><span class="dashboard-kpi-label">Pending approvals</span><strong>${G.length}</strong></div>
|
|
131
|
+
<div><span class="dashboard-kpi-label">Chat sessions</span><strong>${K.length}</strong></div>
|
|
132
|
+
</div>
|
|
133
|
+
${Ae.length?`<div class="dashboard-bars">${Ae.map(F=>`
|
|
134
|
+
<div class="dashboard-bar-row">
|
|
135
|
+
<div class="dashboard-bar-meta">
|
|
136
|
+
<span>${r(F.label)}</span>
|
|
137
|
+
<span class="dashboard-bar-count">${F.value}</span>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="dashboard-bar-track"><span class="dashboard-bar-fill ${F.key}" style="width:${F.pct}%"></span></div>
|
|
140
|
+
</div>
|
|
141
|
+
`).join("")}</div>`:'<p class="tcp-subtle">No swarm task records available.</p>'}
|
|
142
|
+
</section>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<div class="tcp-card">
|
|
146
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
147
|
+
<h3 class="tcp-title">Run Volume (Last 12h)</h3>
|
|
148
|
+
<span class="tcp-subtle text-xs">${P.length} total sampled runs</span>
|
|
149
|
+
</div>
|
|
150
|
+
<div class="dashboard-histogram">
|
|
151
|
+
${be.map(F=>{const X=Math.max(8,Math.round(F.value/Ne*100));return`
|
|
152
|
+
<div class="dashboard-histogram-bin">
|
|
153
|
+
<span class="dashboard-histogram-count">${F.value}</span>
|
|
154
|
+
<span class="dashboard-histogram-bar" style="height:${X}%"></span>
|
|
155
|
+
<span class="dashboard-histogram-label">${r(F.label)}</span>
|
|
156
|
+
</div>
|
|
157
|
+
`}).join("")}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div class="tcp-card">
|
|
162
|
+
<h3 class="tcp-title mb-3">Quick Actions</h3>
|
|
163
|
+
<div class="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
|
|
164
|
+
<button class="tcp-btn w-full justify-start" data-goto="chat"><i data-lucide="message-square"></i> Open Chat</button>
|
|
165
|
+
<button class="tcp-btn w-full justify-start" data-goto="agents"><i data-lucide="clipboard-list"></i> Automations + Cost</button>
|
|
166
|
+
<button class="tcp-btn w-full justify-start" data-goto="swarm"><i data-lucide="workflow"></i> Launch Swarm</button>
|
|
167
|
+
<button class="tcp-btn w-full justify-start" data-goto="mcp"><i data-lucide="plug-zap"></i> Connect MCP</button>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
`,s("view").querySelectorAll("[data-goto]").forEach(F=>{F.addEventListener("click",()=>i(F.dataset.goto))})}function oo(e){const t=String(e||"").trim();return t&&(/^https?:\/\//i.test(t)||/^mailto:/i.test(t))?t:""}function On(e){let t=we(e||"");const n=[];return t=t.replace(/`([^`]+)`/g,(s,r)=>{const i=`@@CODE${n.length}@@`;return n.push(`<code>${we(r)}</code>`),i}),t=t.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(s,r,i)=>{const o=oo(i);return o?`<a href="${we(o)}" target="_blank" rel="noreferrer">${we(r)}</a>`:`${we(r)} (${we(i)})`}),t=t.replace(/(https?:\/\/[^\s<]+)/g,s=>{const r=oo(s);return r?`<a href="${we(r)}" target="_blank" rel="noreferrer">${we(s)}</a>`:we(s)}),t=t.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),t=t.replace(/__([^_]+)__/g,"<strong>$1</strong>"),t=t.replace(/\*([^*]+)\*/g,"<em>$1</em>"),t=t.replace(/_([^_]+)_/g,"<em>$1</em>"),t=t.replace(/~~([^~]+)~~/g,"<s>$1</s>"),t=t.replace(/@@CODE(\d+)@@/g,(s,r)=>n[Number(r)]||""),t}function jg(e){const t=String(e||"").replace(/\r/g,"").split(`
|
|
171
|
+
`),n=[];let s=0;for(;s<t.length;){const r=t[s];if(/^\s*```/.test(r)){const c=[];for(s+=1;s<t.length&&!/^\s*```/.test(t[s]);)c.push(t[s]),s+=1;s<t.length&&(s+=1),n.push(`<pre><code>${we(c.join(`
|
|
172
|
+
`))}</code></pre>`);continue}const i=r.match(/^(#{1,6})\s+(.+)$/);if(i){const c=i[1].length;n.push(`<h${c}>${On(i[2])}</h${c}>`),s+=1;continue}if(/^[-*+]\s+/.test(r)){const c=[];for(;s<t.length&&/^[-*+]\s+/.test(t[s]);)c.push(t[s].replace(/^[-*+]\s+/,"")),s+=1;n.push(`<ul>${c.map(l=>`<li>${On(l)}</li>`).join("")}</ul>`);continue}if(/^\d+\.\s+/.test(r)){const c=[];for(;s<t.length&&/^\d+\.\s+/.test(t[s]);)c.push(t[s].replace(/^\d+\.\s+/,"")),s+=1;n.push(`<ol>${c.map(l=>`<li>${On(l)}</li>`).join("")}</ol>`);continue}if(/^>\s?/.test(r)){const c=[];for(;s<t.length&&/^>\s?/.test(t[s]);)c.push(t[s].replace(/^>\s?/,"")),s+=1;n.push(`<blockquote>${c.map(l=>On(l)).join("<br/>")}</blockquote>`);continue}if(!r.trim()){s+=1;continue}const o=[r];for(s+=1;s<t.length&&t[s].trim()&&!/^(#{1,6})\s+/.test(t[s])&&!/^[-*+]\s+/.test(t[s])&&!/^\d+\.\s+/.test(t[s])&&!/^>\s?/.test(t[s])&&!/^\s*```/.test(t[s]);)o.push(t[s]),s+=1;n.push(`<p>${o.map(c=>On(c)).join("<br/>")}</p>`)}return n.join("")}const qg="control-panel",ec="tandem_control_panel_chat_auto_approve_tools",Vg={md:"text/markdown",txt:"text/plain",csv:"text/csv",json:"application/json",pdf:"application/pdf",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp"};function ao(e=""){const t=String(e).toLowerCase().split(".").pop()||"";return Vg[t]||"application/octet-stream"}function Fg(e,t){if(!e||!t)return t||"";const n=String(e).replace(/[\\/]+$/,""),s=String(t).replace(/^[\\/]+/,"");return`${n}/${s}`}function Ug(){try{return localStorage.getItem(ec)==="1"}catch{return!1}}function Zg(e){try{localStorage.setItem(ec,e?"1":"0")}catch{}}async function Hg(e){const{state:t,byId:n,toast:s,escapeHtml:r,api:i,renderIcons:o,addCleanup:c}=e,l=await qe();t.currentSessionId||(t.currentSessionId=l[0]?.id||"");let d=!1;n("view").innerHTML=`
|
|
173
|
+
<div id="chat-layout" class="chat-layout min-w-0 h-[calc(100vh-2rem)]">
|
|
174
|
+
<aside id="chat-sessions-panel" class="chat-sessions-panel">
|
|
175
|
+
<div class="chat-sessions-header">
|
|
176
|
+
<h3 class="chat-sessions-title"><i data-lucide="clock-3"></i> Sessions</h3>
|
|
177
|
+
<button id="new-session" class="tcp-btn h-8 px-2.5 text-xs"><i data-lucide="plus"></i> New</button>
|
|
178
|
+
</div>
|
|
179
|
+
<div id="session-list" class="chat-session-list"></div>
|
|
180
|
+
</aside>
|
|
181
|
+
<button id="chat-scrim" class="chat-scrim" aria-label="Close sessions"></button>
|
|
182
|
+
<div class="chat-workspace min-h-0 min-w-0">
|
|
183
|
+
<div class="chat-main-shell flex min-h-0 min-w-0 flex-col overflow-hidden">
|
|
184
|
+
<div class="chat-main-header shrink-0">
|
|
185
|
+
<button id="chat-toggle-sessions" type="button" class="chat-icon-btn h-8 w-8" title="Sessions"><i data-lucide="clock-3"></i></button>
|
|
186
|
+
<div class="chat-main-dot"></div>
|
|
187
|
+
<h3 id="chat-title" class="tcp-title chat-main-title">Chat</h3>
|
|
188
|
+
<span id="chat-tool-count" class="chat-main-tools hidden"></span>
|
|
189
|
+
</div>
|
|
190
|
+
<div id="messages" class="chat-messages mb-2 min-h-0 min-w-0 flex-1 space-y-2 overflow-auto p-3"></div>
|
|
191
|
+
<div class="chat-composer shrink-0">
|
|
192
|
+
<div id="chat-attach-row" class="chat-attach-row mb-2 hidden">
|
|
193
|
+
<input id="chat-file-input" type="file" class="hidden" multiple />
|
|
194
|
+
<span id="chat-attach-summary" class="tcp-subtle">0 files attached</span>
|
|
195
|
+
<div id="chat-files" class="chat-files-line"></div>
|
|
196
|
+
</div>
|
|
197
|
+
<div id="chat-upload-progress" class="mb-2 grid gap-1.5"></div>
|
|
198
|
+
<div class="chat-input-wrap">
|
|
199
|
+
<button id="chat-file-pick-inner" type="button" class="chat-icon-btn chat-icon-btn-inner" title="Attach files"><i data-lucide="paperclip"></i></button>
|
|
200
|
+
<textarea id="chat-input" rows="1" class="tcp-input chat-input-with-clip chat-input-modern resize-none border-slate-600/80 bg-slate-800/60" placeholder="Ask anything... (Enter to send, Shift+Enter newline)"></textarea>
|
|
201
|
+
<button id="send-chat" class="chat-send-btn" title="Send"><i data-lucide="send"></i></button>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
<aside class="chat-right-rail hidden min-h-0 flex-col gap-3 overflow-hidden xl:flex">
|
|
206
|
+
<section class="min-h-0">
|
|
207
|
+
<div class="mb-2 flex items-center justify-between">
|
|
208
|
+
<p class="chat-rail-label">Tools</p>
|
|
209
|
+
<span id="chat-rail-tools-count" class="chat-rail-count">0</span>
|
|
210
|
+
</div>
|
|
211
|
+
<div id="chat-tools-list" class="chat-tools-list"></div>
|
|
212
|
+
</section>
|
|
213
|
+
<section class="min-h-0">
|
|
214
|
+
<div class="mb-2 flex items-center justify-between">
|
|
215
|
+
<p class="chat-rail-label">Approvals</p>
|
|
216
|
+
<span id="chat-rail-permissions-count" class="chat-rail-count">0</span>
|
|
217
|
+
</div>
|
|
218
|
+
<div class="mb-2 flex items-center gap-2">
|
|
219
|
+
<button id="chat-approve-all" class="tcp-btn h-7 px-2 text-[11px]">Approve all</button>
|
|
220
|
+
<label class="inline-flex items-center gap-1.5 text-[11px] text-zinc-400">
|
|
221
|
+
<input id="chat-auto-approve" type="checkbox" class="h-3.5 w-3.5 accent-slate-400" />
|
|
222
|
+
Auto
|
|
223
|
+
</label>
|
|
224
|
+
</div>
|
|
225
|
+
<div id="chat-permissions-list" class="chat-tools-activity"></div>
|
|
226
|
+
</section>
|
|
227
|
+
<section class="min-h-0 flex-1">
|
|
228
|
+
<div class="mb-2 flex items-center justify-between">
|
|
229
|
+
<p class="chat-rail-label">Tool Activity</p>
|
|
230
|
+
<button id="chat-tools-clear" class="tcp-btn h-7 px-2 text-[11px]">Clear</button>
|
|
231
|
+
</div>
|
|
232
|
+
<div id="chat-tools-activity" class="chat-tools-activity"></div>
|
|
233
|
+
</section>
|
|
234
|
+
</aside>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
`;const p=n("chat-layout"),f=n("chat-sessions-panel"),b=n("chat-scrim"),w=n("session-list"),h=n("messages"),_=n("chat-input"),A=n("send-chat"),$=n("chat-file-input"),O=n("chat-file-pick-inner"),V=n("chat-attach-row"),T=n("chat-files"),S=n("chat-upload-progress"),M=n("chat-attach-summary"),C=n("chat-title"),I=n("chat-tool-count"),L=n("chat-rail-tools-count"),P=n("chat-rail-permissions-count"),K=n("chat-permissions-list"),se=n("chat-approve-all"),G=n("chat-auto-approve"),gt=n("chat-tools-list"),St=n("chat-tools-activity"),he=Array.isArray(t.chatUploadedFiles)?t.chatUploadedFiles:[];t.chatUploadedFiles=he;const ue=new Map,ie=[],_e=new Set,pe=[],He=new Set;let Se=Ug(),xe=!1,Ae=[],$e=!1;function be(g){d=!!g,p.classList.toggle("sessions-open",d),f.classList.toggle("open",d),b.classList.toggle("open",d)}function Ne(){_.style.height="0px",_.style.height=`${Math.min(_.scrollHeight,180)}px`}async function qe(){try{const g=await t.client.sessions.list({pageSize:50});if(Array.isArray(g))return g;if(Array.isArray(g?.sessions))return g.sessions}catch{}try{const g=await i("/api/engine/session?page_size=50");return Array.isArray(g)?g:Array.isArray(g?.sessions)?g.sessions:[]}catch{return[]}}function Ee(){const g=String(t.providerDefault||"").trim(),v=String(t.providerDefaultModel||"").trim();return!g||!v?null:{providerID:g,modelID:v}}async function vt(){const g=Ee();if(g)return g;try{const v=await t.client.providers.config(),E=String(v?.default||"").trim(),q=String(v?.providers?.[E]?.default_model||"").trim();if(E&&(t.providerDefault=E),q&&(t.providerDefaultModel=q),E&&q)return{providerID:E,modelID:q}}catch{}return Ee()}async function ke(){const g=await vt(),v={title:`Chat ${new Date().toLocaleTimeString()}`};g&&(v.provider=g.providerID,v.model=g.modelID);const E=await t.client.sessions.create(v),q=await t.client.sessions.get(E).catch(()=>({id:E,title:E}));return l.unshift(q),t.currentSessionId=E,X(),on(),await ut(),await Je(),E}function ct(g){const v=Number(g||0);return v<1024?`${v} B`:v<1024*1024?`${(v/1024).toFixed(1)} KB`:`${(v/(1024*1024)).toFixed(1)} MB`}function yt(){const g=l.find(E=>E.id===t.currentSessionId),v=String(g?.title||"").trim();return v||(t.currentSessionId?`Session ${t.currentSessionId.slice(0,8)}`:"Chat")}function Be(){C.textContent=yt();const g=Ae.length;if(g>0){const v=`${g} tool${g===1?"":"s"}`;I.textContent=v,I.classList.remove("hidden"),L.textContent=String(g)}else I.classList.add("hidden"),L.textContent="0"}function bt(g){return g==="completed"?"chat-tool-chip-ok":g==="failed"?"chat-tool-chip-failed":"chat-tool-chip-running"}function F(){gt.innerHTML=Ae.slice(0,32).map(g=>`<button type="button" class="chat-tool-pill" data-tool-insert="${r(g)}" title="Insert ${r(g)}">${r(g)}</button>`).join("")||'<p class="chat-rail-empty">No tools loaded.</p>',gt.querySelectorAll("[data-tool-insert]").forEach(g=>{g.addEventListener("click",()=>{const v=String(g.dataset.toolInsert||"").trim();v&&(_.value=_.value.trim()?`${_.value} ${v}`:v,_.focus())})}),St.innerHTML=ie.slice(0,24).map(g=>{const v=new Date(g.at).toLocaleTimeString();return`<div class="chat-tool-chip ${bt(g.status)}" title="${r(v)}">${r(g.tool)}: ${r(g.status)}</div>`}).join("")||'<p class="chat-rail-empty">No tool events yet.</p>',Be()}function X(){ie.splice(0,ie.length),_e.clear(),F()}function Re(g,v,E=""){const q=String(g||"").trim();if(q){if(E){if(_e.has(E))return;_e.add(E),_e.size>1e3&&_e.clear()}ie.unshift({id:`${q}:${v}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`,tool:q,status:v,at:Date.now()}),ie.length>80&&(ie.length=80),F()}}function Mt(g,v=0){const E=String(g||"").trim();if(!E)return;const q=document.createElement("div");q.className="chat-msg user",q.innerHTML=`
|
|
238
|
+
<div class="chat-msg-role">User</div>
|
|
239
|
+
<pre class="max-w-full whitespace-pre-wrap break-all font-mono text-xs text-slate-200">${r(E)}</pre>
|
|
240
|
+
${v>0?`<div class="mt-1 text-[10px] text-slate-400">${v} attachment${v===1?"":"s"}</div>`:""}
|
|
241
|
+
`,h.appendChild(q),h.scrollTop=h.scrollHeight}function Ve(g){return String(g||"").trim().replace(/\s+/g," ").replace(/[<>]/g,"")}function lt(g){const v=g||{},E=v.call||v.toolCall||v.part||{};return Ve(v.tool||v.name||v.toolName||v.tool_id||v.toolID||E.tool||E.name||E.toolName||"")}function An(g){const v=g||{},E=v.call||v.toolCall||v.part||{};return String(v.callID||v.toolCallID||v.tool_call_id||v.id||E.callID||E.toolCallID||E.tool_call_id||E.id||"").trim()}function Pt(g,v=""){const E=g?.properties||{};return String(g?.runId||g?.runID||g?.run_id||E.runID||E.runId||E.run_id||E.run?.id||v).trim()}function sn(g){if(!g)return null;const v=g.request||g.approval||g.permission||{},E=String(g.id||g.requestID||g.requestId||g.approvalID||v.id||v.requestID||v.requestId||"").trim();if(!E)return null;const q=String(g.sessionId||g.sessionID||g.session_id||v.sessionId||v.sessionID||v.session_id||"").trim();return{id:E,tool:Ve(g.tool||v.tool||v.name||"tool")||"tool",permission:String(g.permission||v.permission||"").trim(),pattern:String(g.pattern||v.pattern||"").trim(),sessionId:q,status:String(g.status||v.status||"").trim().toLowerCase()}}function rn(g){const v=String(g||"").trim().toLowerCase();return v?v.includes("approved")||v.includes("rejected")||v.includes("denied")||v.includes("resolved")||v.includes("expired")||v.includes("cancel")||v.includes("complete")||v.includes("done")||v.includes("timeout")?!1:v.includes("pending")||v.includes("request")||v.includes("ask")||v.includes("await")||v.includes("open")||v.includes("queue")||v.includes("new")||v.includes("progress")||v==="unknown":!0}function Gn(g){if(!rn(g?.status))return;const v=pe.findIndex(E=>E.id===g.id);v>=0?pe[v]={...pe[v],...g}:pe.unshift(g)}function Xn(g){const v=pe.findIndex(E=>E.id===g);v>=0&&pe.splice(v,1)}function nt(){const g=pe.length;P.textContent=String(g),se.disabled=g===0||xe,G.checked=Se,K.innerHTML=pe.slice(0,20).map(v=>{const E=He.has(v.id),q=[v.permission,v.pattern].filter(Boolean).join(" ");return`
|
|
242
|
+
<article class="rounded-sm border border-zinc-800 bg-zinc-900/65 px-2 py-1.5">
|
|
243
|
+
<div class="truncate text-[11px] text-zinc-200" title="${r(v.id)}">${r(v.tool)}</div>
|
|
244
|
+
<div class="mt-0.5 text-[10px] text-zinc-500">${r(q||v.id)}</div>
|
|
245
|
+
<div class="mt-1 flex gap-1">
|
|
246
|
+
<button class="tcp-btn h-6 px-1.5 text-[10px]" data-perm-allow="${r(v.id)}" ${E?"disabled":""}>Allow</button>
|
|
247
|
+
<button class="tcp-btn h-6 px-1.5 text-[10px]" data-perm-always="${r(v.id)}" ${E?"disabled":""}>Always</button>
|
|
248
|
+
<button class="tcp-btn-danger h-6 px-1.5 text-[10px]" data-perm-deny="${r(v.id)}" ${E?"disabled":""}>Deny</button>
|
|
249
|
+
</div>
|
|
250
|
+
</article>
|
|
251
|
+
`}).join("")||'<p class="chat-rail-empty">No pending approvals.</p>',K.querySelectorAll("[data-perm-allow]").forEach(v=>{v.addEventListener("click",async()=>{const E=String(v.dataset.permAllow||"").trim();E&&await dt(E,"once")})}),K.querySelectorAll("[data-perm-always]").forEach(v=>{v.addEventListener("click",async()=>{const E=String(v.dataset.permAlways||"").trim();E&&await dt(E,"always")})}),K.querySelectorAll("[data-perm-deny]").forEach(v=>{v.addEventListener("click",async()=>{const E=String(v.dataset.permDeny||"").trim();E&&await dt(E,"deny")})})}async function dt(g,v,E=!1){if(!g||He.has(g))return;const q=v==="allow"?"once":v;He.add(g),nt();try{await t.client.permissions.reply(g,q),Xn(g),E||s("ok",`Permission ${q==="deny"?"denied":"approved"} (${g}).`)}catch(Z){E||s("err",Z instanceof Error?Z.message:String(Z))}finally{He.delete(g),nt(),ut()}}async function xt(){if(!(!Se||xe||pe.length===0)){xe=!0,nt();try{for(const g of[...pe])await dt(g.id,"always",!0)}finally{xe=!1,nt()}}}async function ut(){const g=await t.client.permissions.list().catch(()=>({requests:[]})),v=Array.isArray(g?.requests)?g.requests:[],E=String(t.currentSessionId||"").trim();pe.splice(0,pe.length);for(const q of v){const Z=sn(q);Z&&(Z.sessionId&&E&&Z.sessionId!==E||rn(Z.status)&&pe.push(Z))}nt(),xt()}function $t(g){return(Array.isArray(g)?g:Array.isArray(g?.tools)?g.tools:[]).map(E=>{if(typeof E=="string")return E;const q=E||{};return String(q.name||q.id||q.tool||"").trim()}).filter(Boolean)}async function Yn(){try{const g=await t.client.listTools().catch(()=>null);let v=$t(g||[]);if(!v.length){const E=await i("/api/engine/tool").catch(()=>[]);v=$t(E||[])}Ae=[...new Set(v)].sort((E,q)=>E.localeCompare(q))}catch{Ae=[]}F()}function st(){const g=[...ue.entries()];if(!g.length){S.innerHTML="";return}S.innerHTML=g.map(([v,E])=>{const q=Math.max(0,Math.min(100,Number(E.progress||0)));return`
|
|
252
|
+
<div class="rounded-lg border border-slate-700/70 bg-slate-900/40 px-2 py-1.5">
|
|
253
|
+
<div class="mb-1 flex items-center justify-between gap-2 text-xs">
|
|
254
|
+
<span class="truncate text-slate-200">${r(E.name)}</span>
|
|
255
|
+
<span class="${E.error?"text-rose-300":"text-slate-400"}">${E.error?r(E.error):`${q}%`}</span>
|
|
256
|
+
</div>
|
|
257
|
+
<div class="h-1.5 overflow-hidden rounded-full bg-slate-800">
|
|
258
|
+
<div class="h-full rounded-full bg-slate-400/80 transition-all duration-150" style="width:${q}%"></div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
`}).join("")}function zt(){if(!he.length){T.innerHTML="",M.textContent="",V.classList.add("hidden");return}const g=he.length;M.textContent=`${g} attached`,V.classList.remove("hidden"),T.innerHTML=he.map((v,E)=>`
|
|
262
|
+
<div class="chat-file-pill min-w-0">
|
|
263
|
+
<span class="chat-file-pill-name" title="${r(v.path)}">${r(v.path)}</span>
|
|
264
|
+
<span class="chat-file-pill-size">${r(ct(v.size))}</span>
|
|
265
|
+
<button class="chat-file-pill-btn chat-file-pill-btn-danger" type="button" data-file-remove="${E}" title="Remove from list"><i data-lucide="x"></i></button>
|
|
266
|
+
</div>
|
|
267
|
+
`).join(""),T.querySelectorAll("[data-file-remove]").forEach(v=>{v.addEventListener("click",()=>{const E=Number(v.dataset.fileRemove);Number.isFinite(E)&&(he.splice(E,1),zt())})}),o(T)}function Zs(g){return new Promise((v,E)=>{const q=`${Date.now()}-${Math.random().toString(16).slice(2)}`;ue.set(q,{name:g.name,progress:0,error:""}),st();const Z=new XMLHttpRequest;Z.open("POST",`/api/files/upload?dir=${encodeURIComponent(qg)}`),Z.withCredentials=!0,Z.responseType="json",Z.setRequestHeader("x-file-name",encodeURIComponent(g.name)),Z.upload.onprogress=ge=>{if(!ge.lengthComputable)return;const Fe=ue.get(q);Fe&&(Fe.progress=ge.loaded/ge.total*100,st())},Z.onerror=()=>{const ge=ue.get(q);ge&&(ge.error="Network error"),st(),setTimeout(()=>{ue.delete(q),st()},1200),E(new Error(`Upload failed: ${g.name}`))},Z.onload=()=>{const ge=Z.response||{};if(Z.status<200||Z.status>=300||ge?.ok===!1){const Fe=ge?.error||`Upload failed (${Z.status})`,kt=ue.get(q);kt&&(kt.error=String(Fe)),st(),setTimeout(()=>{ue.delete(q),st()},1800),E(new Error(String(Fe)));return}ue.delete(q),st(),v(ge)},Z.send(g)})}async function Hs(g){const v=[...g||[]];if(!v.length)return;let E=0;for(const q of v)try{const Z=await Zs(q);he.unshift({name:Z.name||q.name,path:Z.path||q.name,size:Number(Z.size||q.size||0),mime:q.type||ao(Z.name||q.name),url:Z.absPath||Fg(Z.root,Z.path)||Z.path||q.name}),E+=1,zt()}catch(Z){s("err",Z instanceof Error?Z.message:String(Z))}E>0&&s("ok",`Uploaded ${E} file${E===1?"":"s"}.`)}async function Qn(g){await t.client.sessions.delete(g);const v=l.findIndex(E=>E.id===g);v>=0&&l.splice(v,1),t.currentSessionId===g&&(t.currentSessionId=l[0]?.id||"",t.currentSessionId||await ke()),X(),on(),await Je()}function on(){w.innerHTML=l.map(g=>`
|
|
268
|
+
<div class="chat-session-row">
|
|
269
|
+
<button class="chat-session-btn ${g.id===t.currentSessionId?"active":""}" data-sid="${g.id}" title="${r(g.id)}">
|
|
270
|
+
<span class="block truncate">${r(g.title||g.id.slice(0,8))}</span>
|
|
271
|
+
</button>
|
|
272
|
+
<button class="chat-session-del" data-del-sid="${g.id}" title="Delete session">
|
|
273
|
+
<i data-lucide="trash-2"></i>
|
|
274
|
+
</button>
|
|
275
|
+
</div>
|
|
276
|
+
`).join(""),w.querySelectorAll("[data-sid]").forEach(g=>{g.addEventListener("click",async()=>{t.currentSessionId=g.dataset.sid,X(),on(),await ut(),await Je(),be(!1)})}),w.querySelectorAll("[data-del-sid]").forEach(g=>{g.addEventListener("click",async v=>{v.stopPropagation();const E=g.dataset.delSid;if(E&&window.confirm("Delete this session?"))try{await Qn(E),s("ok","Session deleted.")}catch(q){s("err",q instanceof Error?q.message:String(q))}})}),o(w)}async function Je(){if(Be(),!t.currentSessionId){h.innerHTML='<p class="tcp-subtle">Create a session to begin.</p>';return}const g=await t.client.sessions.messages(t.currentSessionId).catch(()=>[]),v=String(t.botName||"Assistant").trim()||"Assistant",E=String(t.botAvatarUrl||"").trim();h.innerHTML=g.map(q=>{const Z=String(q?.info?.role||"unknown"),Fe=r(Z==="assistant"?v:Z==="user"?"User":Z==="system"?"System":Z),kt=Z==="assistant"?`<span class="inline-flex items-center gap-2">${E?`<img src="${r(E)}" alt="${r(v)}" class="h-5 w-5 rounded-full object-cover ring-1 ring-slate-600" />`:""}<span>${Fe}</span></span>`:Fe,W=(q.parts||[]).map(Ot=>Ot.text||"").join(`
|
|
277
|
+
`),re=Z==="assistant"||Z==="system",an=re?`<div class="tcp-markdown tcp-markdown-ai">${jg(W)}</div>`:`<pre class="max-w-full whitespace-pre-wrap break-all font-mono text-xs text-slate-200">${r(W)}</pre>`;return`<div class="chat-msg ${re?"assistant":"user"}"><div class="chat-msg-role">${kt}</div>${an}</div>`}).join(""),h.scrollTop=h.scrollHeight}n("new-session").addEventListener("click",async()=>{be(!1);try{await ke()}catch(g){s("err",g instanceof Error?g.message:String(g))}}),se?.addEventListener("click",async()=>{const g=pe.map(E=>E.id).filter(Boolean);if(!g.length)return;for(const E of g)await dt(E,"once",!0);await ut();const v=g.filter(E=>pe.some(q=>String(q.id||"").trim()===E)).length;v>0?s("warn",`${v} request${v===1?"":"s"} still pending (likely stale/expired).`):s("ok",`Approved ${g.length} pending request${g.length===1?"":"s"}.`)}),G?.addEventListener("change",()=>{Se=!!G.checked,Zg(Se),nt(),Se&&xt()});async function es(){if($e)return;const g=_.value.trim(),v=he.slice(),E=g||(v.length?"Please analyze the attached file(s).":"");if(!(!E&&v.length===0)){_.value="",Ne(),$e=!0,A.disabled=!0;try{t.currentSessionId||await ke(),Mt(E,v.length);const q=await vt();if(!q)throw new Error("No default provider/model configured. Set it in Settings before sending chat.");v.length>0&&s("info",`Sending with ${v.length} attached file${v.length===1?"":"s"}.`);const Z=v.map(D=>({type:"file",mime:D.mime||ao(D.name||D.path),filename:D.name||D.path||"attachment",url:D.url||D.path}));Z.push({type:"text",text:E});const ge=async()=>{const D=await fetch(`/api/engine/session/${encodeURIComponent(t.currentSessionId)}/run`,{method:"GET",credentials:"include"});if(!D.ok)return"";const Q=await D.json().catch(()=>({}));return Q?.active?.runID||Q?.active?.runId||Q?.active?.run_id||""},Fe=async()=>{const D=await ge().catch(()=>"");D&&await fetch(`/api/engine/session/${encodeURIComponent(t.currentSessionId)}/run/${encodeURIComponent(D)}/cancel`,{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({})}).catch(()=>{}),await fetch(`/api/engine/session/${encodeURIComponent(t.currentSessionId)}/cancel`,{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({})}).catch(()=>{});for(let Q=0;Q<50;Q+=1){if(!await ge().catch(()=>""))return!0;await new Promise(Te=>setTimeout(Te,200))}return!1},kt=async()=>fetch(`/api/engine/session/${encodeURIComponent(t.currentSessionId)}/prompt_async?return=run`,{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({parts:Z,model:{providerID:q.providerID,modelID:q.modelID}})});let W=await kt(),re="";if(W.status===409){if(!await Fe())throw new Error("Session has a stuck active run. Cancel it from engine/session and retry.");if(W=await kt(),W.ok){const Q=await W.json().catch(()=>({}));re=Q?.runID||Q?.runId||Q?.run_id||""}else{if(W.status===409)throw new Error("Session is still busy with another run. Please retry in a moment.");{const Q=await W.text().catch(()=>"");throw new Error(`prompt_async retry failed (${W.status}): ${Q}`)}}}else if(W.ok){const D=await W.json().catch(()=>({}));re=D?.runID||D?.runId||D?.run_id||""}else{const D=await W.text().catch(()=>"");throw new Error(`prompt_async failed (${W.status}): ${D}`)}if(!re)throw new Error("No run ID returned from engine.");v.length>0&&(he.splice(0,he.length),zt());let an="",rt=!1;const Ot=r(String(t.botName||"Assistant").trim()||"Assistant"),Kt=String(t.botAvatarUrl||"").trim(),Nt=document.createElement("div");Nt.className="chat-msg assistant",Nt.innerHTML=`
|
|
278
|
+
<div class="chat-msg-role"><span class="inline-flex items-center gap-2">${Kt?`<img src="${r(Kt)}" alt="${Ot}" class="h-5 w-5 rounded-full object-cover ring-1 ring-slate-600" />`:""}<span>${Ot}</span></span></div>
|
|
279
|
+
<div class="tcp-thinking" aria-live="polite">
|
|
280
|
+
<span>Thinking</span>
|
|
281
|
+
<i></i><i></i><i></i>
|
|
282
|
+
</div>
|
|
283
|
+
<pre class="streaming-msg hidden whitespace-pre-wrap break-all font-mono text-xs text-slate-200"></pre>
|
|
284
|
+
`,h.appendChild(Nt),h.scrollTop=h.scrollHeight;const Wt=Nt.querySelector(".tcp-thinking"),pt=Nt.querySelector(".streaming-msg"),Js=new Set(["run.complete","run.completed","session.run.finished","session.run.completed"]),ts=new Set(["run.failed","session.run.failed","run.cancelled","run.canceled","session.run.cancelled","session.run.canceled"]),ns=new Set(["tool.called","tool_call.started","session.tool_call"]),Lt=new Set(["tool.result","tool_call.completed","tool_call.failed","session.tool_result"]);let Tt=!1;const cn=new AbortController;let Dt=null,ln=null,dn="";const ss=3e4,Ks=18e4,En=async(D,Q)=>{const Y=Date.now();for(;Date.now()-Y<Q;){const Te=await ge().catch(()=>D);if(await Je(),!Te||Te!==D)return!0;await new Promise(Ie=>setTimeout(Ie,350))}return!1},Ke=D=>{const Q=String(D||"").trim();return Q!=="server.connected"&&Q!=="engine.lifecycle.ready"},rs=()=>{Dt&&clearTimeout(Dt),Dt=setTimeout(()=>{Tt=!0,dn="no-events-timeout",cn.abort("no-events-timeout")},ss)};rs(),ln=setTimeout(()=>{Tt=!0,dn="max-stream-window",cn.abort("max-stream-window")},Ks);try{for await(const D of t.client.stream(t.currentSessionId,re,{signal:cn.signal})){Ke(D.type)&&rs();const Q=Pt(D);if(D.type==="approval.requested"||D.type==="permission.request"||D.type==="permission.asked"){const Y=sn(D.properties||{});Y?(!Y.sessionId||Y.sessionId===String(t.currentSessionId||"").trim())&&(Gn(Y),nt(),xt()):ut()}if(D.type==="approval.resolved"||D.type==="permission.resolved"||D.type==="permission.replied"){const Y=sn(D.properties||{});Y?.id&&Xn(Y.id),nt(),ut()}if(!(Q&&Q!==re)){if(D.type==="session.response"){const Y=String(D.properties?.delta||"");if(!Y)continue;rt=!0,Wt&&Wt.classList.add("hidden"),pt.classList.remove("hidden"),an+=Y,pt.textContent=an,h.scrollTop=h.scrollHeight}if(ns.has(D.type)){const Y=lt(D.properties)||"tool",Te=An(D.properties);Re(Y,"started",`${Te||Q||re}:${Y}:started`)}if(Lt.has(D.type)){const Y=lt(D.properties)||"tool",Te=An(D.properties),Ie=String(D.properties?.status||D.properties?.state||"").toLowerCase(),wt=D.type==="tool_call.failed"||Ie.includes("fail")||Ie.includes("error")||!!D.properties?.error;Re(Y,wt?"failed":"completed",`${Te||Q||re}:${Y}:${wt?"failed":"completed"}`)}if(D.type==="message.part.updated"){const Y=D.properties?.part||{},Te=String(Y.type||"").trim().toLowerCase().replace(/_/g,"-"),Ie=lt(Y)||lt(D.properties),wt=An(Y),Me=Y?.state,We=String((Me&&typeof Me=="object"?Me.status:Me)||Y.status||"").trim().toLowerCase(),At=!!Y.error||!!(Me&&typeof Me=="object"&&Me.error)||We.includes("fail")||We.includes("error")||We.includes("deny")||We.includes("reject")||We.includes("cancel"),is=!!Y.result||!!Y.output||!!(Me&&typeof Me=="object"&&(Me.output||Me.result))||We.includes("done")||We.includes("complete")||We.includes("success");if(Ie&&(Te==="tool"||Te==="tool-invocation")){const jt=At?"failed":is?"completed":"started";Re(Ie,jt,`${wt||Q||re}:${Ie}:${jt}`)}Ie&&Te==="tool-result"&&Re(Ie,At?"failed":"completed",`${wt||Q||re}:${Ie}:${At?"failed":"completed"}`)}if(ts.has(D.type))throw new Error(String(D.properties?.error||"Run failed."));if((D.type==="session.updated"||D.type==="session.status")&&String(D.properties?.status||"").toLowerCase()==="idle"||Js.has(D.type))break}}}catch(D){const Q=String(D?.message||D||"").toLowerCase();if(!(Tt||Q.includes("abort")||Q.includes("terminated")||Q.includes("networkerror")))throw D}if(Dt&&clearTimeout(Dt),ln&&clearTimeout(ln),Tt){const D=await En(re,45e3);if(await Je(),!D)throw new Error("Run stream timed out and the run is still active. Check engine/provider logs and retry.")}if(!rt&&Wt&&(Wt.innerHTML="<span>Finalizing response...</span>"),await Je(),await new Promise(D=>setTimeout(D,180)),await Je(),await new Promise(D=>setTimeout(D,220)),await Je(),!rt&&await ge().catch(()=>"")===re){if(await En(re,3e4)){await Je();return}const Y=dn||"stream-ended-without-final-delta";throw new Error(`Run ${re} is still active without a final response (${Y}).`)}}catch(q){const Z=q instanceof Error?q.message:String(q),ge=Z.includes("no-events-timeout")||Z.includes("max-stream-window")||Z.includes("AbortError")||Z.toLowerCase().includes("terminated")?"Run stream timed out before events were received. Check engine/provider logs and retry.":Z;s("err",ge),await Je()}finally{$e=!1,A.disabled=!1}}}A.addEventListener("click",()=>{es()}),n("chat-toggle-sessions")?.addEventListener("click",()=>{be(!d)}),b?.addEventListener("click",()=>{be(!1)}),n("chat-tools-clear")?.addEventListener("click",()=>{X()}),O.addEventListener("click",()=>{$.click()}),$.addEventListener("change",async()=>{await Hs($.files),$.value=""}),_.addEventListener("keydown",g=>{g.key==="Enter"&&!g.shiftKey&&(g.preventDefault(),es())}),_.addEventListener("input",()=>{Ne()}),on(),zt(),F(),nt(),Yn(),ut();const Bs=setInterval(()=>{t.route==="chat"&&ut()},2500);c?.(()=>clearInterval(Bs)),!t.currentSessionId&&l.length===0&&await ke().catch(()=>{}),be(!1),Ne(),await Je()}async function et(e){const{state:t,byId:n,toast:s,escapeHtml:r,api:i,renderIcons:o}=e,c=["overview","routines","automations","templates","runs"],l="tcp_agents_wizard_seen_v1",d=()=>{const a=String(window.location.hash||""),[,u=""]=a.split("?"),m=new URLSearchParams(u),y=String(m.get("tab")||"").trim().toLowerCase(),x=c.includes(y)?y:"overview",z=String(m.get("flow")||"").trim().toLowerCase()==="routine"?"routine":"advanced",U=Number.parseInt(String(m.get("step")||"0"),10),J=Number.isFinite(U)?Math.min(2,Math.max(0,U)):0,te=m.has("wizard"),ee=String(m.get("wizard")||"0").trim()==="1";return{tab:x,flow:z,step:J,wizard:ee,wizardProvided:te}},p=(a={})=>{const u=d(),m={tab:c.includes(String(a.tab||"").toLowerCase())?String(a.tab).toLowerCase():u.tab,flow:String(a.flow||u.flow).toLowerCase()==="routine"?"routine":"advanced",step:Number.isFinite(Number(a.step))?Math.min(2,Math.max(0,Number.parseInt(String(a.step),10)||0)):u.step,wizard:typeof a.wizard=="boolean"?a.wizard:String(a.wizard||"").trim()==="1"?!0:a.wizard===0?!1:u.wizard},y=new URLSearchParams;y.set("tab",m.tab),y.set("flow",m.flow),y.set("step",String(m.step)),y.set("wizard",m.wizard?"1":"0");const x=`#/agents?${y.toString()}`;window.location.hash!==x&&(window.location.hash=x)},[f,b,w,h,_,A,$,O,V,T]=await Promise.all([t.client.routines.list().catch(()=>({routines:[]})),t.client.automations.list().catch(()=>({automations:[]})),t.client?.automationsV2?.list?.().catch(()=>({automations:[]}))||Promise.resolve({automations:[]}),t.client.routines.listRuns({limit:100}).catch(()=>({runs:[]})),t.client.automations.listRuns({limit:100}).catch(()=>({runs:[]})),t.client.providers.catalog().catch(()=>({all:[],connected:[],default:null})),t.client.providers.config().catch(()=>({default:null,providers:{}})),t.client.listToolIds().catch(()=>[]),t.client?.mcp?.list?.().catch(()=>({}))||Promise.resolve({}),t.client?.skills?.list?.().catch(()=>({skills:[]}))||Promise.resolve({skills:[]})]),S=f.routines||[],M=b.automations||[],C=Array.isArray(w?.automations)?w.automations:[],I=Array.isArray(h?.runs)?h.runs:[],L=Array.isArray(_?.runs)?_.runs:[],P=Array.isArray(A?.all)?A.all:[],K=$?.providers||{},se=Array.isArray(O)?O.map(a=>String(a||"").trim()).filter(Boolean).sort():[],St=(a=>!a||typeof a!="object"?[]:(Array.isArray(a)?a.map(m=>[String(m?.name||""),m]):Object.entries(a)).map(([m,y])=>{const x=y&&typeof y=="object"?y:{},R=String(x.name||m||"").trim();if(!R)return null;const z=!!x.connected,U=x.enabled!==!1;return{name:R,connected:z,enabled:U}}).filter(Boolean).sort((m,y)=>m.name.localeCompare(y.name)))(V).filter(a=>a.connected&&a.enabled).map(a=>a.name),he=Array.isArray(T?.skills)?T.skills.map(a=>String(a?.name||a?.id||"").trim()).filter(Boolean).sort((a,u)=>a.localeCompare(u)):[],ue=(a="")=>String(a).toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64)||"routine",ie=a=>{if(!a)return"manual";if(typeof a=="string")return a;const u=Number(a?.interval_seconds?.seconds??a?.intervalSeconds?.seconds??a?.intervalSeconds??0);if(u>0)return u%3600===0?`every ${u/3600}h`:u%60===0?`every ${u/60}m`:`every ${u}s`;const m=String(a?.cron?.expression??a?.cron?.cron??a?.expression??a?.cron??"").trim();if(m){const y=m,x=y.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+\*$/);if(x){const z=String(x[1]).padStart(2,"0");return`daily ${String(x[2]).padStart(2,"0")}:${z}`}const R=y.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-6])$/);if(R){const z=String(R[1]).padStart(2,"0"),U=String(R[2]).padStart(2,"0");return`weekly ${["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][Number.parseInt(R[3],10)]||R[3]} ${U}:${z}`}return`cron ${y}`.trim()}return a.type==="manual"?"manual":JSON.stringify(a)},_e=a=>{const u=String(a?.args?.promptFilePath||"").trim();return u||String(a?.entrypoint||a?.prompt||"").match(/(control-panel\/routines\/[A-Za-z0-9._\-\/]+\.md)/)?.[1]||""},pe=a=>{const u=a?.args?.model_policy?.default_model,m=String(u?.provider_id||"").trim(),y=String(u?.model_id||"").trim();return!m||!y?"":`${m}/${y}`},He=(a,u,m)=>{const y=a?.[u]??a?.[m]??[];if(!Array.isArray(y))return[];const x=new Set,R=[];for(const z of y){const U=String(z||"").trim();U&&(x.has(U)||(x.add(U),R.push(U)))}return R},Se=(a,u,m,y)=>{const x=a?.[u];if(typeof x=="boolean")return x;const R=a?.[m];return typeof R=="boolean"?R:y},xe=a=>{const u=new Set,m=[];return String(a||"").split(",").map(y=>y.trim()).filter(Boolean).forEach(y=>{u.has(y)||(u.add(y),m.push(y))}),m},Ae=a=>String(a?.id||a?.routine_id||a?.routineID||a?.routineId||"").trim(),$e=a=>String(a?.id||a?.automation_id||a?.automationID||a?.automationId||"").trim(),be=a=>String(a?.runId||a?.runID||a?.run_id||a?.id||"").trim(),Ne=a=>String(a?.routineId||a?.routine_id||a?.routineID||a?.routineId||"").trim(),qe=a=>String(a?.automationId||a?.automation_id||a?.automationID||a?.automationId||"").trim(),Ee=a=>String(a?.status||"unknown").toLowerCase(),vt=a=>String(a?.detail||a?.reason||"").trim(),ke=a=>{const u=[a?.updatedAtMs,a?.updated_at_ms,a?.finishedAtMs,a?.finished_at_ms,a?.startedAtMs,a?.started_at_ms,a?.createdAtMs,a?.created_at_ms,a?.firedAtMs,a?.fired_at_ms];for(const m of u){const y=Number(m);if(Number.isFinite(y)&&y>0)return y}return 0},ct=a=>{const u=Number(a);return!Number.isFinite(u)||u<=0?"time n/a":new Date(u).toLocaleString()},yt=(a,u=120)=>{const m=String(a||"").trim();return m?m.length>u?`${m.slice(0,u-1)}...`:m:""},Be=a=>{const u=String(a||"").toLowerCase();return u.includes("complete")||u.includes("succeed")?"tcp-badge-info":u.includes("fail")||u.includes("cancel")||u.includes("deny")?"tcp-badge-err":u.includes("block")||u.includes("approval")||u.includes("pause")?"tcp-badge-warn":"tcp-badge-info"},bt=a=>{const u=String(a||"").toLowerCase();return u==="pending_approval"||u.includes("awaiting_approval")},F=(a,u)=>{const m=new Map,y=[...a].sort((x,R)=>ke(R)-ke(x));for(const x of y){const R=u(x);!R||m.has(R)||m.set(R,x)}return m},X=new Map(S.map(a=>[Ae(a),String(a.name||Ae(a)||"Routine").trim()]).filter(([a])=>!!a)),Re=new Map(S.map(a=>[Ae(a),a]).filter(([a])=>!!a)),Mt=new Map(M.map(a=>[$e(a),String(a.name||$e(a)||"Automation").trim()]).filter(([a])=>!!a)),Ve=F(I,Ne),lt=F(L,qe),An=[...I.map(a=>({family:"routine",run:a})),...L.map(a=>({family:"automation",run:a}))].sort((a,u)=>ke(u.run)-ke(a.run)),Pt=[],sn=new Set;for(const a of An){const u=be(a.run),m=a.family==="routine"?Ne(a.run):qe(a.run),y=u||`${a.family}:${m}:${ke(a.run)}:${Ee(a.run)}`;if(!sn.has(y)&&(sn.add(y),Pt.push(a),Pt.length>=30))break}const rn=new Set(M.map(a=>$e(a)).filter(Boolean)),Gn=new Set(S.map(a=>Ae(a)).filter(Boolean)),Xn=rn.size>0&&rn.size===Gn.size&&[...rn].every(a=>Gn.has(a)),nt=Object.fromEntries(Object.entries(K).map(([a,u])=>[a,String(u?.default_model||u?.defaultModel||"").trim()])),dt=P.map(a=>a.id).filter(Boolean),xt=a=>{const u=P.find(m=>m.id===a);return Object.keys(u?.models||{})},ut=String($?.default||A?.default||t.providerDefault||"").trim(),$t=dt.includes(ut)?ut:dt[0]||"",Yn=String(nt[$t]||t.providerDefaultModel||"").trim(),st=xt($t),zt=st.includes(Yn)?Yn:st[0]||"",Zs=P.map(a=>{const u=String(a.name||a.id||"").trim()||a.id;return`<option value="${r(a.id)}" ${a.id===$t?"selected":""}>${r(u)}</option>`}).join("")||'<option value="">No providers found</option>',Hs=st.map(a=>`<option value="${r(a)}" ${a===zt?"selected":""}>${r(a)}</option>`).join("")||'<option value="">No models found</option>',Qn=se.map(a=>`<option value="${r(a)}"></option>`).join(""),on=M.map(a=>{const u=$e(a),m=lt.get(u),y=Ee(m),x=be(m),R=yt(vt(m)),z=bt(y)&&!!x;return`<div class="tcp-list-item">
|
|
285
|
+
<div class="flex items-center justify-between gap-2">
|
|
286
|
+
<span>${r(String(a.name||u||"Automation"))}</span>
|
|
287
|
+
<div class="flex items-center gap-2">
|
|
288
|
+
<span class="tcp-subtle">${r(String(a.status||""))}</span>
|
|
289
|
+
${u?`<button data-run-automation="${r(u)}" class="tcp-btn h-7 px-2 text-xs"><i data-lucide="play"></i> Run</button>`:""}
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
${m?`<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
293
|
+
<span class="${Be(y)}">${r(y)}</span>
|
|
294
|
+
<span class="tcp-subtle">${r(ct(ke(m)))}</span>
|
|
295
|
+
<span class="tcp-subtle font-mono">${r(x||"run n/a")}</span>
|
|
296
|
+
</div>
|
|
297
|
+
${z?`<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
298
|
+
<button data-run-review="approve" data-run-id="${r(x)}" data-run-family="automation" class="tcp-btn h-7 px-2 text-xs">Approve</button>
|
|
299
|
+
<button data-run-review="deny" data-run-id="${r(x)}" data-run-family="automation" class="tcp-btn-danger h-7 px-2 text-xs">Deny</button>
|
|
300
|
+
</div>`:""}
|
|
301
|
+
${R?`<div class="mt-1 text-xs text-slate-400">${r(R)}</div>`:""}`:'<div class="mt-1 text-xs text-slate-500">No automation runs yet.</div>'}
|
|
302
|
+
</div>`}).join("")||'<p class="tcp-subtle">No automations.</p>',Je=a=>String(a?.automation_id||a?.automationId||a?.id||a?.automationID||"").trim(),es=C.map(a=>{const u=Je(a),m=String(a?.status||"draft").toLowerCase(),y=Number(a?.next_fire_at_ms||a?.nextFireAtMs||0),x=Array.isArray(a?.flow?.nodes)?a.flow.nodes.length:0,R=Array.isArray(a?.agents)?a.agents.length:0;return`<div class="tcp-list-item">
|
|
303
|
+
<div class="flex items-center justify-between gap-2">
|
|
304
|
+
<span>${r(String(a?.name||u||"Automation"))}</span>
|
|
305
|
+
<div class="flex items-center gap-2">
|
|
306
|
+
<span class="${Be(m)}">${r(m)}</span>
|
|
307
|
+
${u?`<button data-v2-run-now="${r(u)}" class="tcp-btn h-7 px-2 text-xs"><i data-lucide="play"></i> Run</button>`:""}
|
|
308
|
+
${u?`<button data-v2-toggle="${r(u)}" data-v2-next="${m==="paused"?"resume":"pause"}" class="tcp-btn h-7 px-2 text-xs">
|
|
309
|
+
<i data-lucide="${m==="paused"?"play-circle":"pause-circle"}"></i> ${m==="paused"?"Resume":"Pause"}
|
|
310
|
+
</button>`:""}
|
|
311
|
+
${u?`<button data-v2-runs="${r(u)}" class="tcp-btn h-7 px-2 text-xs"><i data-lucide="list"></i> Runs</button>`:""}
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
315
|
+
<span class="tcp-subtle">${R} agents</span>
|
|
316
|
+
<span class="tcp-subtle">${x} nodes</span>
|
|
317
|
+
<span class="tcp-subtle">${y>0?ct(y):"manual schedule"}</span>
|
|
318
|
+
<span class="tcp-subtle font-mono">${r(u||"id n/a")}</span>
|
|
319
|
+
</div>
|
|
320
|
+
</div>`}).join("")||'<p class="tcp-subtle">No advanced automations.</p>',Bs=Pt.map(({family:a,run:u})=>{const m=a==="routine",y=m?Ne(u):qe(u),x=be(u),R=m?X.get(y)||y||"Routine":Mt.get(y)||y||"Automation",z=Ee(u),U=bt(z)&&!!x,J=yt(vt(u),180);return`<div class="tcp-list-item">
|
|
321
|
+
<div class="flex items-center justify-between gap-2">
|
|
322
|
+
<span class="font-medium">${r(R)}</span>
|
|
323
|
+
<div class="flex items-center gap-2">
|
|
324
|
+
${x?`<button data-inspect-run="${r(x)}" data-run-family="${r(a)}" class="tcp-btn h-7 px-2 text-xs">Details</button>`:""}
|
|
325
|
+
${U?`<button data-run-review="approve" data-run-id="${r(x)}" data-run-family="${r(a)}" class="tcp-btn h-7 px-2 text-xs">Approve</button>
|
|
326
|
+
<button data-run-review="deny" data-run-id="${r(x)}" data-run-family="${r(a)}" class="tcp-btn-danger h-7 px-2 text-xs">Deny</button>`:""}
|
|
327
|
+
<span class="${Be(z)}">${r(z)}</span>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
331
|
+
<span class="tcp-subtle">${m?"Routine":"Automation"}</span>
|
|
332
|
+
<span class="tcp-subtle">${r(ct(ke(u)))}</span>
|
|
333
|
+
<span class="tcp-subtle font-mono">${r(x||"run n/a")}</span>
|
|
334
|
+
</div>
|
|
335
|
+
${J?`<div class="mt-1 text-xs text-slate-400">${r(J)}</div>`:""}
|
|
336
|
+
</div>`}).join("")||'<p class="tcp-subtle">No runs yet.</p>',g=a=>{const u=Number(a?.total_tokens??a?.totalTokens??0);return Number.isFinite(u)&&u>=0?u:0},v=a=>{const u=Number(a?.estimated_cost_usd??a?.estimatedCostUsd??0);return Number.isFinite(u)&&u>=0?u:0},q=Date.now()-24*36e5;let Z=0,ge=0;const Fe=new Map;for(const a of[...I,...L]){const u=ke(a),m=g(a),y=v(a);u>=q&&(Z+=m,ge+=y);const x=Ne(a)||qe(a)||"unknown",R=Fe.get(x)||{cost:0};R.cost+=y,Fe.set(x,R)}const kt=[...Fe.entries()].map(([a,u])=>({id:a,cost:u.cost})).sort((a,u)=>u.cost-a.cost).slice(0,3),W=d();if(!W.wizard&&!W.wizardProvided&&!S.length&&!M.length&&!C.length){let a=!1;try{a=localStorage.getItem(l)==="1"}catch{a=!1}a||setTimeout(()=>{p({tab:"overview",wizard:!0,flow:"advanced",step:0})},0)}const re=(...a)=>a.includes(W.tab)?"":" hidden",an=W.flow==="routine"?["Choose flow","Configure routine","Run + monitor"]:["Choose flow","Configure agents","Run + monitor"];n("view").innerHTML=`
|
|
337
|
+
<div class="tcp-card" data-agents-panel="header">
|
|
338
|
+
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
339
|
+
<div>
|
|
340
|
+
<h3 class="tcp-title">Automations</h3>
|
|
341
|
+
<p class="tcp-subtle text-xs">Build, schedule, and operate routines and multi-agent automations.</p>
|
|
342
|
+
</div>
|
|
343
|
+
<button id="agents-launch-wizard" class="tcp-btn-primary"><i data-lucide="sparkles"></i> Launch Walkthrough</button>
|
|
344
|
+
</div>
|
|
345
|
+
<div class="agents-tabs mt-3">
|
|
346
|
+
<button class="agents-tab-btn ${W.tab==="overview"?"active":""}" data-agents-tab="overview">Overview</button>
|
|
347
|
+
<button class="agents-tab-btn ${W.tab==="routines"?"active":""}" data-agents-tab="routines">Routines</button>
|
|
348
|
+
<button class="agents-tab-btn ${W.tab==="automations"?"active":""}" data-agents-tab="automations">Automations</button>
|
|
349
|
+
<button class="agents-tab-btn ${W.tab==="templates"?"active":""}" data-agents-tab="templates">Templates</button>
|
|
350
|
+
<button class="agents-tab-btn ${W.tab==="runs"?"active":""}" data-agents-tab="runs">Runs & Approvals</button>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
<div class="tcp-card${re("overview")}" data-agents-panel="overview">
|
|
354
|
+
<h3 class="tcp-title mb-2">Overview</h3>
|
|
355
|
+
<div class="dashboard-kpis mb-3">
|
|
356
|
+
<div><span class="dashboard-kpi-label">Routines</span><strong>${S.length}</strong></div>
|
|
357
|
+
<div><span class="dashboard-kpi-label">Automations</span><strong>${C.length}</strong></div>
|
|
358
|
+
<div><span class="dashboard-kpi-label">Pending approvals</span><strong>${Pt.filter(a=>bt(Ee(a.run))).length}</strong></div>
|
|
359
|
+
<div><span class="dashboard-kpi-label">Recent runs</span><strong>${Pt.length}</strong></div>
|
|
360
|
+
</div>
|
|
361
|
+
<div class="rounded-xl border border-slate-700/60 bg-slate-900/30 p-3">
|
|
362
|
+
<div class="mb-2 flex items-center justify-between gap-2">
|
|
363
|
+
<span class="font-medium">Automations + Cost (24h)</span>
|
|
364
|
+
<span class="tcp-subtle text-xs">dashboard has full analytics</span>
|
|
365
|
+
</div>
|
|
366
|
+
<div class="grid gap-2 md:grid-cols-3">
|
|
367
|
+
<div class="tcp-subtle">Tokens: <span class="font-mono text-slate-200">${Z.toLocaleString()}</span></div>
|
|
368
|
+
<div class="tcp-subtle">Estimated cost: <span class="font-mono text-slate-200">$${ge.toFixed(4)}</span></div>
|
|
369
|
+
<div class="tcp-subtle">Top owners: <span class="font-mono text-slate-200">${r(kt.map(a=>a.id).join(", ")||"none")}</span></div>
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
<div class="tcp-card${W.wizard?"":" hidden"}" data-agents-panel="wizard">
|
|
374
|
+
<div class="flex items-center justify-between gap-2">
|
|
375
|
+
<h3 class="tcp-title">Walkthrough Wizard</h3>
|
|
376
|
+
<button id="agents-wizard-close" class="tcp-btn">Close</button>
|
|
377
|
+
</div>
|
|
378
|
+
<div class="agents-steps mt-3">
|
|
379
|
+
${an.map((a,u)=>`<span class="agents-step-chip ${W.step===u?"active":""}">${u+1}. ${r(a)}</span>`).join("")}
|
|
380
|
+
</div>
|
|
381
|
+
<div class="mt-3 rounded-xl border border-slate-700/60 bg-slate-900/35 p-3">
|
|
382
|
+
${W.step===0?`<p class="tcp-subtle mb-3">Pick what you want to build first.</p>
|
|
383
|
+
<div class="flex flex-wrap gap-2">
|
|
384
|
+
<button data-wizard-flow="advanced" class="tcp-btn ${W.flow==="advanced"?"border-slate-300/80":""}">Advanced automation</button>
|
|
385
|
+
<button data-wizard-flow="routine" class="tcp-btn ${W.flow==="routine"?"border-slate-300/80":""}">Routine</button>
|
|
386
|
+
</div>`:W.step===1?`<p class="tcp-subtle mb-3">${W.flow==="routine"?"Configure schedule, model, and policy for your routine.":"Configure schedule, per-agent models/skills, and DAG nodes."}</p>
|
|
387
|
+
<button id="agents-wizard-open-builder" class="tcp-btn-primary">${W.flow==="routine"?"Open Routine Builder":"Open Automation Builder"}</button>`:`<p class="tcp-subtle mb-3">Launch runs and monitor approvals, pause/resume, and outcomes.</p>
|
|
388
|
+
<button id="agents-wizard-open-runs" class="tcp-btn-primary">Open Runs & Approvals</button>`}
|
|
389
|
+
</div>
|
|
390
|
+
<div class="mt-3 flex items-center justify-between">
|
|
391
|
+
<button id="agents-wizard-prev" class="tcp-btn" ${W.step<=0?"disabled":""}>Back</button>
|
|
392
|
+
<button id="agents-wizard-next" class="tcp-btn-primary">${W.step>=2?"Finish":"Next"}</button>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
<div class="tcp-card${re("templates")}" data-agents-panel="templates">
|
|
396
|
+
<h3 class="tcp-title mb-3">Automation Templates</h3>
|
|
397
|
+
<div class="grid gap-2 md:grid-cols-2">
|
|
398
|
+
<button class="tcp-btn justify-start" data-template-id="github_bug_hunter">GitHub bug hunter</button>
|
|
399
|
+
<button class="tcp-btn justify-start" data-template-id="code_generation_pipeline">Code generation pipeline</button>
|
|
400
|
+
<button class="tcp-btn justify-start" data-template-id="release_notes_changelog">Release notes + changelog</button>
|
|
401
|
+
<button class="tcp-btn justify-start" data-template-id="marketing_content_engine">Marketing content engine</button>
|
|
402
|
+
<button class="tcp-btn justify-start" data-template-id="sales_lead_outreach">Sales lead outreach</button>
|
|
403
|
+
<button class="tcp-btn justify-start" data-template-id="productivity_inbox_to_tasks">Productivity: inbox to tasks</button>
|
|
404
|
+
</div>
|
|
405
|
+
<p class="tcp-subtle mt-3 text-xs">Selecting a template pre-fills the advanced automation builder and opens the walkthrough.</p>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="tcp-card${re("routines")}" data-agents-panel="routines">
|
|
408
|
+
<h3 class="tcp-title mb-3">Create Routine</h3>
|
|
409
|
+
<p id="routine-form-mode" class="mb-2 text-xs text-slate-400">Creating new routine</p>
|
|
410
|
+
<div class="grid gap-3 md:grid-cols-2">
|
|
411
|
+
<input id="routine-name" class="tcp-input" placeholder="Routine name" />
|
|
412
|
+
<select id="routine-schedule-mode" class="tcp-select">
|
|
413
|
+
<option value="interval">Every X minutes/hours</option>
|
|
414
|
+
<option value="daily">Daily at specific time</option>
|
|
415
|
+
<option value="weekly">Weekly on a specific day/time</option>
|
|
416
|
+
<option value="customCron">Custom cron</option>
|
|
417
|
+
<option value="manual">Manual only</option>
|
|
418
|
+
</select>
|
|
419
|
+
</div>
|
|
420
|
+
<div id="routine-interval-controls" class="mt-3 grid gap-3 md:grid-cols-2">
|
|
421
|
+
<input id="routine-interval-value" class="tcp-input" type="number" min="1" max="10000" step="1" value="30" />
|
|
422
|
+
<select id="routine-interval-unit" class="tcp-select">
|
|
423
|
+
<option value="minutes">Minutes</option>
|
|
424
|
+
<option value="hours">Hours</option>
|
|
425
|
+
</select>
|
|
426
|
+
</div>
|
|
427
|
+
<div id="routine-daily-controls" class="mt-3 grid hidden gap-3 md:grid-cols-2">
|
|
428
|
+
<input id="routine-time" class="tcp-input" type="time" value="09:00" />
|
|
429
|
+
<div class="tcp-subtle self-center text-xs">Runs once per day at selected time</div>
|
|
430
|
+
</div>
|
|
431
|
+
<div id="routine-weekly-controls" class="mt-3 grid hidden gap-3 md:grid-cols-2">
|
|
432
|
+
<select id="routine-weekday" class="tcp-select">
|
|
433
|
+
<option value="1">Monday</option>
|
|
434
|
+
<option value="2">Tuesday</option>
|
|
435
|
+
<option value="3">Wednesday</option>
|
|
436
|
+
<option value="4">Thursday</option>
|
|
437
|
+
<option value="5">Friday</option>
|
|
438
|
+
<option value="6">Saturday</option>
|
|
439
|
+
<option value="0">Sunday</option>
|
|
440
|
+
</select>
|
|
441
|
+
<input id="routine-weekly-time" class="tcp-input" type="time" value="09:00" />
|
|
442
|
+
</div>
|
|
443
|
+
<div id="routine-cron-controls" class="mt-3 grid hidden gap-3 md:grid-cols-1">
|
|
444
|
+
<input id="routine-cron" class="tcp-input hidden" placeholder="Cron e.g. 0 * * * *" />
|
|
445
|
+
</div>
|
|
446
|
+
<div class="mt-2 text-xs text-slate-400">
|
|
447
|
+
<span id="routine-schedule-preview" class="font-mono">Schedule: every 30m</span>
|
|
448
|
+
</div>
|
|
449
|
+
<div class="mt-3 grid gap-3 md:grid-cols-2">
|
|
450
|
+
<div>
|
|
451
|
+
<label class="mb-1 block text-sm text-slate-300">Routine Provider</label>
|
|
452
|
+
<select id="routine-model-provider" class="tcp-select" ${P.length?"":"disabled"}>
|
|
453
|
+
${Zs}
|
|
454
|
+
</select>
|
|
455
|
+
</div>
|
|
456
|
+
<div>
|
|
457
|
+
<label class="mb-1 block text-sm text-slate-300">Routine Model</label>
|
|
458
|
+
<select id="routine-model-id" class="tcp-select" ${st.length?"":"disabled"}>
|
|
459
|
+
${Hs}
|
|
460
|
+
</select>
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
<div class="mt-1 text-xs text-slate-400">
|
|
464
|
+
Model route for this routine: <span id="routine-model-preview" class="font-mono">${r($t&&zt?`${$t}/${zt}`:"default engine route")}</span>
|
|
465
|
+
</div>
|
|
466
|
+
<div class="mt-3 rounded-xl border border-slate-700/70 bg-slate-900/35 p-3">
|
|
467
|
+
<label class="mb-2 inline-flex items-center gap-2 text-xs text-slate-200">
|
|
468
|
+
<input id="routine-allow-everything" type="checkbox" class="h-4 w-4 accent-slate-400" />
|
|
469
|
+
Allow everything (no approval, all tools, external integrations)
|
|
470
|
+
</label>
|
|
471
|
+
<label class="mb-1 block text-sm text-slate-300">Tool Allowlist (optional)</label>
|
|
472
|
+
<input
|
|
473
|
+
id="routine-allowed-tools"
|
|
474
|
+
list="routine-tool-options"
|
|
475
|
+
class="tcp-input font-mono text-xs"
|
|
476
|
+
placeholder="Comma-separated tool IDs (leave empty to allow all tools by policy)"
|
|
477
|
+
/>
|
|
478
|
+
<datalist id="routine-tool-options">${Qn}</datalist>
|
|
479
|
+
<div id="routine-tool-scope-preview" class="mt-1 text-xs text-slate-400">Tool scope: all tools allowed by policy</div>
|
|
480
|
+
<div class="mt-2 grid gap-2 md:grid-cols-2">
|
|
481
|
+
<label class="inline-flex items-center gap-2 text-xs text-slate-300">
|
|
482
|
+
<input id="routine-requires-approval" type="checkbox" class="h-4 w-4 accent-slate-400" checked />
|
|
483
|
+
Require approval for external side effects
|
|
484
|
+
</label>
|
|
485
|
+
<label class="inline-flex items-center gap-2 text-xs text-slate-300">
|
|
486
|
+
<input id="routine-external-integrations" type="checkbox" class="h-4 w-4 accent-slate-400" />
|
|
487
|
+
Allow external integrations (MCP/connectors)
|
|
488
|
+
</label>
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
<div class="mt-4 rounded-xl border border-slate-700/70 bg-slate-900/35 p-3">
|
|
492
|
+
<div class="mb-2 flex items-center justify-between gap-2">
|
|
493
|
+
<label class="inline-flex items-center gap-2 text-sm text-slate-200">
|
|
494
|
+
<input id="routine-use-file" type="checkbox" class="h-4 w-4 accent-slate-400" checked />
|
|
495
|
+
Save prompt as Markdown file (recommended)
|
|
496
|
+
</label>
|
|
497
|
+
<button id="save-routine-file" class="tcp-btn"><i data-lucide="save"></i> Save Prompt File</button>
|
|
498
|
+
</div>
|
|
499
|
+
<input id="routine-file-path" class="tcp-input mb-3 font-mono text-xs" value="control-panel/routines/new-routine.md" />
|
|
500
|
+
<textarea id="routine-prompt" class="tcp-input" rows="6" placeholder="Write your routine instructions in Markdown..."></textarea>
|
|
501
|
+
<div class="mt-2 text-xs text-slate-400">
|
|
502
|
+
Tip: keep goals, constraints, and output format in this file so you can improve it anytime without rewriting the routine.
|
|
503
|
+
</div>
|
|
504
|
+
</div>
|
|
505
|
+
<div class="mt-3 grid gap-2 md:grid-cols-[1fr_auto]">
|
|
506
|
+
<div class="text-xs text-slate-400">Create will use the selected schedule and entry prompt.</div>
|
|
507
|
+
<div class="flex items-center justify-end gap-2">
|
|
508
|
+
<button id="cancel-edit-routine" class="tcp-btn hidden">Cancel Edit</button>
|
|
509
|
+
<button id="create-routine" class="tcp-btn-primary"><i data-lucide="plus"></i> Create</button>
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
<div class="tcp-card${re("routines")}" data-agents-panel="routines">
|
|
514
|
+
<h3 class="tcp-title mb-3">Routines (${S.length})</h3>
|
|
515
|
+
<div id="routine-list" class="tcp-list"></div>
|
|
516
|
+
</div>
|
|
517
|
+
<div class="tcp-card${re("automations")}" data-agents-panel="automations">
|
|
518
|
+
<h3 class="tcp-title mb-3">Automations (${M.length})</h3>
|
|
519
|
+
${Xn?'<p class="tcp-subtle mb-2">Automation endpoints currently mirror routine records in this workspace.</p>':""}
|
|
520
|
+
<div class="tcp-list">${on}</div>
|
|
521
|
+
</div>
|
|
522
|
+
<div class="tcp-card${re("automations")}" data-agents-panel="automations">
|
|
523
|
+
<h3 class="tcp-title mb-3">Automation Builder</h3>
|
|
524
|
+
<div class="grid gap-3 md:grid-cols-2">
|
|
525
|
+
<input id="automation-v2-name" class="tcp-input" placeholder="Automation name" />
|
|
526
|
+
<input id="automation-v2-description" class="tcp-input" placeholder="Description (optional)" />
|
|
527
|
+
</div>
|
|
528
|
+
<div class="mt-3 grid gap-3 md:grid-cols-3">
|
|
529
|
+
<select id="automation-v2-schedule-type" class="tcp-select">
|
|
530
|
+
<option value="manual">Manual</option>
|
|
531
|
+
<option value="interval">Interval</option>
|
|
532
|
+
<option value="cron">Cron</option>
|
|
533
|
+
</select>
|
|
534
|
+
<input id="automation-v2-interval-seconds" class="tcp-input" type="number" min="1" value="3600" placeholder="Interval seconds" />
|
|
535
|
+
<input id="automation-v2-cron" class="tcp-input" placeholder="Cron expression (UTC by default)" />
|
|
536
|
+
</div>
|
|
537
|
+
<div class="mt-3 grid gap-3 md:grid-cols-3">
|
|
538
|
+
<input id="automation-v2-timezone" class="tcp-input" value="UTC" />
|
|
539
|
+
<select id="automation-v2-misfire" class="tcp-select">
|
|
540
|
+
<option value="run_once">run_once</option>
|
|
541
|
+
<option value="skip">skip</option>
|
|
542
|
+
<option value="catch_up">catch_up</option>
|
|
543
|
+
</select>
|
|
544
|
+
<input id="automation-v2-agent-count" class="tcp-input" type="number" min="1" max="12" value="2" />
|
|
545
|
+
</div>
|
|
546
|
+
<div class="mt-3 grid gap-3 md:grid-cols-[1fr_auto]">
|
|
547
|
+
<select id="automation-v2-preset" class="tcp-select">
|
|
548
|
+
<option value="">Choose preset...</option>
|
|
549
|
+
<option value="github_bug_hunter">GitHub bug hunter</option>
|
|
550
|
+
<option value="code_generation_pipeline">Code generation pipeline</option>
|
|
551
|
+
<option value="release_notes_changelog">Release notes + changelog</option>
|
|
552
|
+
<option value="marketing_content_engine">Marketing content engine</option>
|
|
553
|
+
<option value="sales_lead_outreach">Sales lead outreach</option>
|
|
554
|
+
<option value="productivity_inbox_to_tasks">Productivity: inbox to tasks</option>
|
|
555
|
+
</select>
|
|
556
|
+
<button id="automation-v2-apply-preset" class="tcp-btn"><i data-lucide="sparkles"></i> Apply Preset</button>
|
|
557
|
+
</div>
|
|
558
|
+
<div class="mt-2 text-xs text-slate-400">Per-agent model routing: choose provider + model per agent. Defaults come from Settings. Use “Custom” only when needed.</div>
|
|
559
|
+
<div class="mt-3">
|
|
560
|
+
<button id="automation-v2-generate-agents" class="tcp-btn"><i data-lucide="users"></i> Generate Agent Rows</button>
|
|
561
|
+
</div>
|
|
562
|
+
<datalist id="automation-v2-skill-options">${he.map(a=>`<option value="${r(a)}"></option>`).join("")}</datalist>
|
|
563
|
+
<datalist id="automation-v2-tool-options">${Qn}</datalist>
|
|
564
|
+
<div id="automation-v2-agents-editor" class="mt-3 grid gap-2"></div>
|
|
565
|
+
<div class="mt-4">
|
|
566
|
+
<div class="mb-2 flex items-center justify-between">
|
|
567
|
+
<h4 class="text-sm font-semibold text-slate-200">Flow Nodes (DAG)</h4>
|
|
568
|
+
<button id="automation-v2-add-node" class="tcp-btn h-7 px-2 text-xs"><i data-lucide="plus"></i> Add Node</button>
|
|
569
|
+
</div>
|
|
570
|
+
<div id="automation-v2-nodes-editor" class="grid gap-2"></div>
|
|
571
|
+
</div>
|
|
572
|
+
<div class="mt-4 flex items-center justify-end gap-2">
|
|
573
|
+
<button id="automation-v2-create" class="tcp-btn-primary"><i data-lucide="save"></i> Create Automation</button>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
<div class="tcp-card${re("automations")}" data-agents-panel="automations">
|
|
577
|
+
<h3 class="tcp-title mb-3">Advanced Automations (${C.length})</h3>
|
|
578
|
+
<div class="tcp-list">${es}</div>
|
|
579
|
+
</div>
|
|
580
|
+
<div class="tcp-card${re("automations")}" data-agents-panel="automations">
|
|
581
|
+
<h3 class="tcp-title mb-2">Automation Run Inspector</h3>
|
|
582
|
+
<div id="automation-v2-run-inspector" class="tcp-list">
|
|
583
|
+
<p class="tcp-subtle">Click an automation "Runs" button to inspect and control run state.</p>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
<div class="tcp-card${re("runs")}" data-agents-panel="runs">
|
|
587
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
588
|
+
<h3 class="tcp-title">Recent Runs (${Pt.length})</h3>
|
|
589
|
+
<button id="refresh-runs" class="tcp-btn"><i data-lucide="refresh-cw"></i> Refresh</button>
|
|
590
|
+
</div>
|
|
591
|
+
<div class="tcp-list">${Bs}</div>
|
|
592
|
+
</div>
|
|
593
|
+
<div class="tcp-card${re("runs")}" data-agents-panel="runs">
|
|
594
|
+
<h3 class="tcp-title mb-2">Run Inspector</h3>
|
|
595
|
+
<div id="run-inspector" class="tcp-list">
|
|
596
|
+
<p class="tcp-subtle">Pick any recent run and click Details to inspect status, full detail, and artifacts.</p>
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
`,n("view").querySelectorAll("[data-agents-tab]").forEach(a=>a.addEventListener("click",()=>{const u=String(a.getAttribute("data-agents-tab")||"").trim().toLowerCase();c.includes(u)&&p({tab:u})})),n("agents-launch-wizard")?.addEventListener("click",()=>{p({wizard:!0,step:0})}),n("agents-wizard-close")?.addEventListener("click",()=>{try{localStorage.setItem(l,"1")}catch{}p({wizard:!1})}),n("agents-wizard-prev")?.addEventListener("click",()=>{p({step:Math.max(0,W.step-1)})}),n("agents-wizard-next")?.addEventListener("click",()=>{if(W.step>=2){try{localStorage.setItem(l,"1")}catch{}p({wizard:!1,tab:"runs"});return}p({step:Math.min(2,W.step+1)})}),n("view").querySelectorAll("[data-wizard-flow]").forEach(a=>a.addEventListener("click",()=>{const u=String(a.getAttribute("data-wizard-flow")||"").trim().toLowerCase();p({flow:u==="routine"?"routine":"advanced"})})),n("agents-wizard-open-builder")?.addEventListener("click",()=>{p({tab:W.flow==="routine"?"routines":"automations",step:2})}),n("agents-wizard-open-runs")?.addEventListener("click",()=>{p({tab:"runs",step:2})});const rt=n("routine-list");rt.innerHTML=S.map(a=>{const u=Ae(a),m=Ve.get(u),y=Ee(m),x=be(m),R=yt(vt(m)),z=pe(a),U=String(a.status||"active").toLowerCase(),J=He(a,"allowed_tools","allowedTools"),te=Se(a,"requires_approval","requiresApproval",!0),ee=Se(a,"external_integrations_allowed","externalIntegrationsAllowed",!1),ae=U==="paused",Pe=bt(y)&&!!x;return`
|
|
600
|
+
<div class="tcp-list-item flex items-center justify-between gap-3">
|
|
601
|
+
<div>
|
|
602
|
+
<div class="font-medium">${r(a.name||u||"Unnamed routine")}</div>
|
|
603
|
+
<div class="mt-1 flex items-center gap-2">
|
|
604
|
+
<span class="${ae?"tcp-badge-warn":"tcp-badge-info"}">${r(U)}</span>
|
|
605
|
+
<span class="tcp-subtle font-mono">${r(ie(a.schedule))}</span>
|
|
606
|
+
</div>
|
|
607
|
+
<div class="mt-1 text-xs text-slate-400 font-mono">${r(z||"default engine route")}</div>
|
|
608
|
+
<div class="mt-1 text-xs text-slate-400">
|
|
609
|
+
tools: ${r(J.length?J.join(", "):"all (no explicit allowlist)")}
|
|
610
|
+
</div>
|
|
611
|
+
<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
612
|
+
<span class="${te?"tcp-badge-warn":"tcp-badge-info"}">${te?"approval required":"no approval gate"}</span>
|
|
613
|
+
<span class="${ee?"tcp-badge-info":"tcp-badge-warn"}">${ee?"external integrations allowed":"external integrations blocked"}</span>
|
|
614
|
+
</div>
|
|
615
|
+
${m?`<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
616
|
+
<span class="${Be(y)}">${r(y)}</span>
|
|
617
|
+
<span class="tcp-subtle">${r(ct(ke(m)))}</span>
|
|
618
|
+
<span class="tcp-subtle font-mono">${r(x||"run n/a")}</span>
|
|
619
|
+
</div>
|
|
620
|
+
${R?`<div class="mt-1 text-xs text-slate-400">${r(R)}</div>`:""}`:'<div class="mt-1 text-xs text-slate-500">No runs yet.</div>'}
|
|
621
|
+
${_e(a)?`<div class="mt-1 text-xs text-slate-400 font-mono">${r(_e(a))}</div>`:""}
|
|
622
|
+
</div>
|
|
623
|
+
<div class="flex gap-2">
|
|
624
|
+
<button data-run="${r(u)}" class="tcp-btn"><i data-lucide="play"></i> Run</button>
|
|
625
|
+
${Pe?`<button data-run-review="approve" data-run-id="${r(x)}" data-run-family="routine" class="tcp-btn">Approve</button>
|
|
626
|
+
<button data-run-review="deny" data-run-id="${r(x)}" data-run-family="routine" class="tcp-btn-danger">Deny</button>`:""}
|
|
627
|
+
<button data-toggle-status="${r(u)}" data-next-status="${ae?"active":"paused"}" class="tcp-btn">
|
|
628
|
+
<i data-lucide="${ae?"play-circle":"pause-circle"}"></i> ${ae?"Resume":"Pause"}
|
|
629
|
+
</button>
|
|
630
|
+
<button data-edit-routine="${r(u)}" class="tcp-btn"><i data-lucide="pencil"></i> Edit</button>
|
|
631
|
+
${_e(a)?`<button data-edit-file="${r(_e(a))}" class="tcp-btn"><i data-lucide="folder-open"></i> Prompt File</button>`:""}
|
|
632
|
+
<button data-del="${r(u)}" class="tcp-btn-danger"><i data-lucide="trash-2"></i></button>
|
|
633
|
+
</div>
|
|
634
|
+
</div>`}).join("")||'<p class="tcp-subtle">No routines.</p>',o(rt),n("refresh-runs").addEventListener("click",()=>{et(e)});const Ot=n("run-inspector"),Kt=n("automation-v2-run-inspector"),Nt=t.client?.automationsV2,Wt=!!Nt;Wt||(Kt.innerHTML='<p class="tcp-subtle">Advanced automation client API is unavailable in this build.</p>');const pt=async a=>{if(!Wt)throw new Error("Advanced automation API unavailable.");return a(Nt)},Js=['<option value="">Default from settings</option>',...dt.map(a=>`<option value="${r(a)}">${r(a)}</option>`),'<option value="__custom__">Custom provider...</option>'].join(""),ts=(a,u={})=>`
|
|
635
|
+
<div data-v2-agent-row="${a}" class="rounded-xl border border-slate-700/60 bg-slate-900/30 p-3">
|
|
636
|
+
<div class="mb-2 text-xs text-slate-300 font-semibold">Agent ${a+1}</div>
|
|
637
|
+
<div class="grid gap-2 md:grid-cols-2">
|
|
638
|
+
<input data-v2-agent-field="agent_id" data-v2-agent-index="${a}" class="tcp-input font-mono text-xs" value="${r(String(u.agent_id||`agent-${a+1}`))}" />
|
|
639
|
+
<input data-v2-agent-field="display_name" data-v2-agent-index="${a}" class="tcp-input" placeholder="Display name" value="${r(String(u.display_name||`Agent ${a+1}`))}" />
|
|
640
|
+
<select data-v2-agent-field="model_provider_select" data-v2-agent-index="${a}" class="tcp-select">${Js}</select>
|
|
641
|
+
<input data-v2-agent-field="model_provider_custom" data-v2-agent-index="${a}" class="tcp-input" placeholder="Custom provider id (enabled when Custom provider selected)" value="${r(String(u.model_provider||""))}" />
|
|
642
|
+
<select data-v2-agent-field="model_id_select" data-v2-agent-index="${a}" class="tcp-select">
|
|
643
|
+
<option value="">Default model for provider</option>
|
|
644
|
+
<option value="__custom__">Custom model...</option>
|
|
645
|
+
</select>
|
|
646
|
+
<input data-v2-agent-field="model_id_custom" data-v2-agent-index="${a}" class="tcp-input" placeholder="Custom model id (enabled when Custom model selected)" value="${r(String(u.model_id||""))}" />
|
|
647
|
+
<input data-v2-agent-field="skills" data-v2-agent-index="${a}" class="tcp-input" list="automation-v2-skill-options" placeholder="Skills (text tags, comma-separated)" value="${r(String(Array.isArray(u.skills)?u.skills.join(", "):u.skills||""))}" />
|
|
648
|
+
<select data-v2-agent-field="tool_mode" data-v2-agent-index="${a}" class="tcp-select">
|
|
649
|
+
<option value="standard">Standard tools (recommended)</option>
|
|
650
|
+
<option value="read_only">Read-only tools</option>
|
|
651
|
+
<option value="custom">Custom allow/deny policy</option>
|
|
652
|
+
</select>
|
|
653
|
+
<div class="md:col-span-2 rounded-lg border border-slate-700/60 bg-slate-900/30 p-2">
|
|
654
|
+
<div class="mb-1 text-xs text-slate-400">Allowed MCP servers for this agent</div>
|
|
655
|
+
<div class="grid gap-2 sm:grid-cols-2">
|
|
656
|
+
${St.length?St.map(m=>{const y=Array.isArray(u.mcp_servers)&&u.mcp_servers.includes(m);return`<label class="inline-flex items-center gap-2 text-xs text-slate-300">
|
|
657
|
+
<input data-v2-agent-field="mcp_server_option" data-v2-agent-index="${a}" type="checkbox" value="${r(m)}" ${y?"checked":""} class="h-4 w-4 accent-slate-400" />
|
|
658
|
+
${r(m)}
|
|
659
|
+
</label>`}).join(""):'<span class="text-xs text-slate-500">No connected MCP servers found. Connect servers in MCP tab.</span>'}
|
|
660
|
+
</div>
|
|
661
|
+
</div>
|
|
662
|
+
<input data-v2-agent-field="allowlist" data-v2-agent-index="${a}" class="tcp-input md:col-span-2" list="automation-v2-tool-options" placeholder="Custom tool allowlist (comma-separated)" value="${r(String(Array.isArray(u.allowlist)?u.allowlist.join(", "):u.allowlist||""))}" />
|
|
663
|
+
<input data-v2-agent-field="denylist" data-v2-agent-index="${a}" class="tcp-input md:col-span-2" list="automation-v2-tool-options" placeholder="Custom tool denylist (comma-separated)" value="${r(String(Array.isArray(u.denylist)?u.denylist.join(", "):u.denylist||""))}" />
|
|
664
|
+
</div>
|
|
665
|
+
</div>
|
|
666
|
+
`,ns=(a,u={})=>`
|
|
667
|
+
<div data-v2-node-row="${a}" class="rounded-xl border border-slate-700/60 bg-slate-900/30 p-3">
|
|
668
|
+
<div class="mb-2 text-xs text-slate-300 font-semibold">Node ${a+1}</div>
|
|
669
|
+
<div class="grid gap-2 md:grid-cols-2">
|
|
670
|
+
<input data-v2-node-field="node_id" data-v2-node-index="${a}" class="tcp-input font-mono text-xs" value="${r(String(u.node_id||`node-${a+1}`))}" />
|
|
671
|
+
<input data-v2-node-field="agent_id" data-v2-node-index="${a}" class="tcp-input font-mono text-xs" value="${r(String(u.agent_id||"agent-1"))}" />
|
|
672
|
+
<input data-v2-node-field="objective" data-v2-node-index="${a}" class="tcp-input md:col-span-2" placeholder="Node objective" value="${r(String(u.objective||""))}" />
|
|
673
|
+
<input data-v2-node-field="depends_on" data-v2-node-index="${a}" class="tcp-input md:col-span-2 font-mono text-xs" placeholder="depends_on csv (node-1,node-2)" value="${r(String(Array.isArray(u.depends_on)?u.depends_on.join(", "):u.depends_on||""))}" />
|
|
674
|
+
<input data-v2-node-field="timeout_ms" data-v2-node-index="${a}" class="tcp-input" type="number" min="0" placeholder="timeout ms" value="${r(String(u.timeout_ms||""))}" />
|
|
675
|
+
</div>
|
|
676
|
+
</div>
|
|
677
|
+
`,Lt=a=>String(a||"").split(",").map(u=>u.trim()).filter(Boolean),Tt=a=>{const u=n("view"),m=it=>u.querySelector(`[data-v2-agent-index="${a}"][data-v2-agent-field="${it}"]`),y=m("model_provider_select"),x=m("model_provider_custom"),R=m("model_id_select"),z=m("model_id_custom");if(!y||!x||!R||!z)return;const U=y.value==="__custom__",J=String(y.value||"").trim(),te=U?String(x.value||"").trim():J||$t||"";x.disabled=!U,x.classList.toggle("opacity-60",!U);const ee=te?xt(te):[],ae=String(z.value||"").trim();R.innerHTML=['<option value="">Default model for provider</option>',...ee.map(it=>`<option value="${r(it)}">${r(it)}</option>`),'<option value="__custom__">Custom model...</option>'].join("");const Pe=String(R.value||"").trim();!!ae&&ee.includes(ae)?R.value=ae:ae||Pe==="__custom__"?R.value="__custom__":R.value="";const me=R.value==="__custom__";z.disabled=!me,z.classList.toggle("opacity-60",!me)},cn=()=>{const a=[...n("automation-v2-agents-editor").querySelectorAll("[data-v2-agent-row]")];for(const u of a){const m=String(u.getAttribute("data-v2-agent-index")||"").trim();if(!m)continue;const y=n("view"),x=ve=>y.querySelector(`[data-v2-agent-index="${m}"][data-v2-agent-field="${ve}"]`),R=x("model_provider_select"),z=x("model_provider_custom"),U=x("model_id_select");x("model_id_custom");const J=x("tool_mode"),te=x("allowlist"),ee=x("denylist"),ae=Lt(String(te?.value||"")),Pe=Lt(String(ee?.value||"")),Qe=ae.length===1&&ae[0]==="read"&&!Pe.length;J&&(J.value=Qe?"read_only":ae.length||Pe.length?"custom":"standard");const me=String(z?.value||"").trim();R&&(me&&dt.includes(me)?R.value=me:me?R.value="__custom__":R.value=""),Tt(m),R&&R.dataset.wired!=="1"&&(R.dataset.wired="1",R.addEventListener("change",()=>Tt(m))),z&&z.dataset.wired!=="1"&&(z.dataset.wired="1",z.addEventListener("input",()=>Tt(m))),U&&U.dataset.wired!=="1"&&(U.dataset.wired="1",U.addEventListener("change",()=>Tt(m)));const it=()=>{if(!J||!te||!ee)return;const Ce=String(J.value||"standard")==="custom";te.disabled=!Ce,ee.disabled=!Ce,te.classList.toggle("opacity-60",!Ce),ee.classList.toggle("opacity-60",!Ce)};it(),J&&J.dataset.wired!=="1"&&(J.dataset.wired="1",J.addEventListener("change",it))}},Dt=()=>{const a=Math.max(1,Math.min(12,Number.parseInt(String(n("automation-v2-agent-count")?.value||"2"),10)||2));n("automation-v2-agents-editor").innerHTML=Array.from({length:a},(u,m)=>ts(m)).join(""),cn()},ln=()=>{const a=n("automation-v2-nodes-editor"),u=a.querySelectorAll("[data-v2-node-row]").length;a.insertAdjacentHTML("beforeend",ns(u))},dn=(a=[],u=[])=>{const m=Array.isArray(a)&&a.length?a:[{agent_id:"agent-1"}];n("automation-v2-agent-count").value=String(Math.min(12,Math.max(1,m.length))),n("automation-v2-agents-editor").innerHTML=m.slice(0,12).map((x,R)=>ts(R,x)).join(""),cn();const y=Array.isArray(u)&&u.length?u:[{node_id:"node-1",agent_id:"agent-1"}];n("automation-v2-nodes-editor").innerHTML=y.map((x,R)=>ns(R,x)).join("")},ss={github_bug_hunter:{name:"GitHub Bug Hunter",description:"Monitor issues, reproduce, patch, and verify fixes automatically.",schedule:{type:"interval",interval_seconds:3600,timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"triage",display_name:"Issue Triage",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",skills:["issue-triage"],mcp_servers:["github","composio"],allowlist:["read","mcp.github.*","mcp.composio.*"]},{agent_id:"fixer",display_name:"Fix Implementer",model_provider:"openrouter",model_id:"anthropic/claude-3.5-sonnet",skills:["coding"],mcp_servers:["github"],allowlist:["read","write","edit","bash","mcp.github.*"]},{agent_id:"qa",display_name:"Regression Tester",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",skills:["testing"],mcp_servers:["github"],allowlist:["read","bash","mcp.github.*"]}],nodes:[{node_id:"scan-issues",agent_id:"triage",objective:"Find high-signal open bugs and collect repro clues."},{node_id:"implement-fix",agent_id:"fixer",objective:"Implement minimal safe fix and prepare patch summary.",depends_on:["scan-issues"]},{node_id:"run-tests",agent_id:"qa",objective:"Run targeted checks and report verification status.",depends_on:["implement-fix"]}]},code_generation_pipeline:{name:"Code Generation Pipeline",description:"Draft implementation, refine quality, and validate quickly.",schedule:{type:"manual",timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"planner",display_name:"Planner",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read"]},{agent_id:"builder",display_name:"Builder",model_provider:"openrouter",model_id:"anthropic/claude-3.5-sonnet",allowlist:["read","write","edit","bash"]},{agent_id:"reviewer",display_name:"Reviewer",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","bash"]}],nodes:[{node_id:"plan",agent_id:"planner",objective:"Produce implementation plan with acceptance criteria."},{node_id:"implement",agent_id:"builder",objective:"Generate and refine code changes from plan.",depends_on:["plan"]},{node_id:"validate",agent_id:"reviewer",objective:"Run checks/tests and summarize risks.",depends_on:["implement"]}]},release_notes_changelog:{name:"Release Notes + Changelog",description:"Collect changes and draft release comms.",schedule:{type:"cron",cron_expression:"0 15 * * 5",timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"collector",display_name:"Change Collector",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","bash","mcp.github.*"],mcp_servers:["github"]},{agent_id:"writer",display_name:"Release Writer",model_provider:"openrouter",model_id:"anthropic/claude-3.5-sonnet",allowlist:["read","write","edit"]}],nodes:[{node_id:"collect",agent_id:"collector",objective:"Gather merged PRs/issues since last release."},{node_id:"draft",agent_id:"writer",objective:"Draft release notes and changelog sections.",depends_on:["collect"]}]},marketing_content_engine:{name:"Marketing Content Engine",description:"Generate campaign-ready social + email content from product updates.",schedule:{type:"interval",interval_seconds:86400,timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"research",display_name:"Trend Research",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["websearch","webfetch","read"]},{agent_id:"copy",display_name:"Copywriter",model_provider:"openrouter",model_id:"anthropic/claude-3.5-sonnet",allowlist:["read","write","edit"]},{agent_id:"editor",display_name:"Brand Editor",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","edit"]}],nodes:[{node_id:"market-scan",agent_id:"research",objective:"Find relevant trends and competitor angles."},{node_id:"draft-assets",agent_id:"copy",objective:"Draft LinkedIn post, email blurb, and CTA variations.",depends_on:["market-scan"]},{node_id:"brand-check",agent_id:"editor",objective:"Align tone/style and produce final approved copy.",depends_on:["draft-assets"]}]},sales_lead_outreach:{name:"Sales Lead Outreach",description:"Enrich leads and generate personalized outreach drafts.",schedule:{type:"interval",interval_seconds:21600,timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"enrichment",display_name:"Lead Enrichment",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","websearch","mcp.composio.*"],mcp_servers:["composio"]},{agent_id:"outreach",display_name:"Outreach Writer",model_provider:"openrouter",model_id:"anthropic/claude-3.5-sonnet",allowlist:["read","write","edit","mcp.composio.*"],mcp_servers:["composio"]}],nodes:[{node_id:"enrich-leads",agent_id:"enrichment",objective:"Enrich lead list with role/company context."},{node_id:"draft-outreach",agent_id:"outreach",objective:"Create personalized outreach drafts and follow-up options.",depends_on:["enrich-leads"]}]},productivity_inbox_to_tasks:{name:"Inbox to Tasks",description:"Convert inbound messages into prioritized action items and calendar-ready summaries.",schedule:{type:"interval",interval_seconds:1800,timezone:"UTC",misfire_policy:"run_once"},agents:[{agent_id:"classifier",display_name:"Inbox Classifier",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","mcp.composio.*"],mcp_servers:["composio"]},{agent_id:"planner",display_name:"Task Planner",model_provider:"openrouter",model_id:"openai/gpt-4o-mini",allowlist:["read","write","edit","todo_write"]}],nodes:[{node_id:"classify",agent_id:"classifier",objective:"Classify inbox items into urgent, important, and informational."},{node_id:"task-plan",agent_id:"planner",objective:"Generate prioritized tasks with due windows and concise summaries.",depends_on:["classify"]}]}};Dt(),ln(),n("view").querySelectorAll("[data-template-id]").forEach(a=>a.addEventListener("click",()=>{const u=String(a.getAttribute("data-template-id")||"").trim(),m=ss[u];if(!m){s("err","Preset not found.");return}n("automation-v2-preset").value=u,n("automation-v2-name").value=String(m.name||""),n("automation-v2-description").value=String(m.description||"");const y=m.schedule||{};n("automation-v2-schedule-type").value=String(y.type||"manual"),n("automation-v2-cron").value=String(y.cron_expression||""),n("automation-v2-interval-seconds").value=String(y.interval_seconds||3600),n("automation-v2-timezone").value=String(y.timezone||"UTC"),n("automation-v2-misfire").value=String(y.misfire_policy||"run_once"),dn(m.agents||[],m.nodes||[]),p({tab:"automations",wizard:!0,flow:"advanced",step:1}),s("ok",`Template loaded: ${m.name}`)})),n("automation-v2-generate-agents")?.addEventListener("click",()=>{Dt(),s("ok","Agent rows regenerated.")}),n("automation-v2-add-node")?.addEventListener("click",()=>{ln()}),n("automation-v2-apply-preset")?.addEventListener("click",()=>{const a=String(n("automation-v2-preset")?.value||"").trim();if(!a){s("err","Choose a preset first.");return}const u=ss[a];if(!u){s("err","Preset not found.");return}n("automation-v2-name").value=String(u.name||""),n("automation-v2-description").value=String(u.description||"");const m=u.schedule||{};n("automation-v2-schedule-type").value=String(m.type||"manual"),n("automation-v2-cron").value=String(m.cron_expression||""),n("automation-v2-interval-seconds").value=String(m.interval_seconds||3600),n("automation-v2-timezone").value=String(m.timezone||"UTC"),n("automation-v2-misfire").value=String(m.misfire_policy||"run_once"),dn(u.agents||[],u.nodes||[]),s("ok",`Preset applied: ${u.name}`)}),n("automation-v2-create")?.addEventListener("click",async()=>{try{const a=String(n("automation-v2-name")?.value||"").trim();if(!a)throw new Error("Automation name is required.");const u=String(n("automation-v2-description")?.value||"").trim(),m=String(n("automation-v2-schedule-type")?.value||"manual").trim(),y=String(n("automation-v2-timezone")?.value||"UTC").trim()||"UTC",x=String(n("automation-v2-misfire")?.value||"run_once").trim(),R=String(n("automation-v2-cron")?.value||"").trim(),z=Number.parseInt(String(n("automation-v2-interval-seconds")?.value||"3600"),10);if(m==="cron"&&!R)throw new Error("Cron expression is required for cron schedule.");if(m==="interval"&&!(Number.isFinite(z)&&z>0))throw new Error("Interval seconds must be greater than 0.");const U=[...n("automation-v2-agents-editor").querySelectorAll("[data-v2-agent-row]")],J=new Set,te=[];for(const me of U){const it=String(me.getAttribute("data-v2-agent-index")||""),ve=er=>n("view").querySelector(`[data-v2-agent-index="${it}"][data-v2-agent-field="${er}"]`)?.value||"",Ce=String(ve("agent_id")).trim();if(!Ce)continue;if(J.has(Ce))throw new Error(`Duplicate agent_id: ${Ce}`);J.add(Ce);const zn=String(ve("model_provider_select")).trim(),us=String(ve("model_provider_custom")).trim(),un=String(ve("model_id_select")).trim(),Ys=String(ve("model_id_custom")).trim(),li=zn==="__custom__"?us:zn||String(ve("model_provider")).trim(),di=un==="__custom__"?Ys:un||String(ve("model_id")).trim(),Qs=String(ve("tool_mode")).trim()||"standard",wc=[...n("view").querySelectorAll(`[data-v2-agent-index="${it}"][data-v2-agent-field="mcp_server_option"]:checked`)].map(er=>String(er.value||"").trim()).filter(Boolean),_c=Qs==="custom"?Lt(ve("allowlist")):Qs==="read_only"?["read"]:[],Sc=Qs==="custom"?Lt(ve("denylist")):[];te.push({agent_id:Ce,display_name:String(ve("display_name")).trim()||Ce,model_policy:li&&di?{default_model:{provider_id:li,model_id:di}}:void 0,skills:Lt(ve("skills")),tool_policy:{allowlist:_c,denylist:Sc},mcp_policy:{allowed_servers:wc}})}if(!te.length)throw new Error("At least one agent is required.");const ee=[...n("automation-v2-nodes-editor").querySelectorAll("[data-v2-node-row]")],ae=new Set,Pe=[];for(const me of ee){const it=String(me.getAttribute("data-v2-node-index")||""),ve=Ys=>n("view").querySelector(`[data-v2-node-index="${it}"][data-v2-node-field="${Ys}"]`)?.value||"",Ce=String(ve("node_id")).trim(),zn=String(ve("objective")).trim(),us=String(ve("agent_id")).trim();if(!Ce||!zn||!us)continue;if(ae.has(Ce))throw new Error(`Duplicate node_id: ${Ce}`);ae.add(Ce);const un=Number.parseInt(String(ve("timeout_ms")).trim(),10);Pe.push({node_id:Ce,objective:zn,agent_id:us,depends_on:Lt(ve("depends_on")),timeout_ms:Number.isFinite(un)&&un>0?un:void 0})}if(!Pe.length)throw new Error("At least one flow node is required.");const Qe={name:a,description:u||void 0,status:"active",schedule:{type:m,cron_expression:m==="cron"?R:void 0,interval_seconds:m==="interval"?z:void 0,timezone:y,misfire_policy:x},agents:te,flow:{nodes:Pe},execution:{max_parallel_agents:Math.min(te.length,4)}};await pt(me=>me.create(Qe)),s("ok","Automation created."),et(e)}catch(a){s("err",a instanceof Error?a.message:String(a))}});const Ks=async(a,u,m)=>{const y=String(u||"").toLowerCase()==="automation",x=String(m||"").toLowerCase()==="deny"?"deny":"approve";if(!a)throw new Error("Run ID is missing.");if(x==="approve"){y?await t.client.automations.approveRun(a,"approved from control panel"):await t.client.routines.approveRun(a,"approved from control panel");return}y?await t.client.automations.denyRun(a,"denied from control panel"):await t.client.routines.denyRun(a,"denied from control panel")},En=a=>{a.querySelectorAll("[data-run-review]").forEach(u=>{u.dataset.wired!=="1"&&(u.dataset.wired="1",u.addEventListener("click",async()=>{const m=String(u.dataset.runId||"").trim(),y=String(u.dataset.runFamily||"routine").trim().toLowerCase(),x=String(u.dataset.runReview||"approve").trim().toLowerCase();if(!m){s("err","Run ID is missing.");return}const R=[...n("view").querySelectorAll("[data-run-review]")].filter(U=>String(U.dataset.runId||"").trim()===m&&String(U.dataset.runFamily||"routine").trim().toLowerCase()===y),z=new Map;for(const U of R)z.set(U,U.innerHTML),U.disabled=!0,U.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i>',o(U);try{await Ks(m,y,x),s("ok",`${x==="deny"?"Denied":"Approved"} ${y} run ${m}.`),setTimeout(()=>{et(e)},250)}catch(U){s("err",U instanceof Error?U.message:String(U));for(const J of R)J.isConnected&&(J.disabled=!1,J.innerHTML=z.get(J)||J.innerHTML,o(J))}}))})};En(n("view")),n("view").querySelectorAll("[data-inspect-run]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.inspectRun||"").trim(),m=String(a.dataset.runFamily||"routine").trim();if(!u){s("err","Run ID is missing.");return}const y=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Loading',o(a);try{let x=await t.client.routines.getRun(u).catch(()=>null),R=await t.client.routines.listArtifacts(u).catch(()=>null);if(!x&&m==="automation"&&(x=await t.client.automations.getRun(u).catch(()=>null),R=await t.client.automations.listArtifacts(u).catch(()=>null)),!x)throw new Error("Run details not found.");const z=Array.isArray(R?.artifacts)?R.artifacts:[],U=He(x,"allowed_tools","allowedTools"),J=Ee(x),te=Se(x,"requires_approval","requiresApproval",!0),ee=Se(x,"external_integrations_allowed","externalIntegrationsAllowed",!1);Ot.innerHTML=`
|
|
678
|
+
<div class="tcp-list-item">
|
|
679
|
+
<div class="mb-2 flex flex-wrap items-center gap-2">
|
|
680
|
+
<span class="${Be(J)}">${r(J)}</span>
|
|
681
|
+
<span class="tcp-subtle font-mono">${r(u)}</span>
|
|
682
|
+
<span class="tcp-subtle">${r(ct(ke(x)))}</span>
|
|
683
|
+
</div>
|
|
684
|
+
<div class="mb-2 text-xs text-slate-300">
|
|
685
|
+
${r(U.length?`Allowlist (${U.length}): ${U.join(", ")}`:"No explicit allowlist: all tools are available subject to policy.")}
|
|
686
|
+
</div>
|
|
687
|
+
<div class="mb-2 flex flex-wrap items-center gap-2 text-xs">
|
|
688
|
+
<span class="${te?"tcp-badge-warn":"tcp-badge-info"}">${te?"approval required":"no approval gate"}</span>
|
|
689
|
+
<span class="${ee?"tcp-badge-info":"tcp-badge-warn"}">${ee?"external integrations allowed":"external integrations blocked"}</span>
|
|
690
|
+
</div>
|
|
691
|
+
${bt(J)?`<div class="mb-2 flex flex-wrap items-center gap-2 text-xs">
|
|
692
|
+
<button data-run-review="approve" data-run-id="${r(u)}" data-run-family="${r(m)}" class="tcp-btn h-7 px-2 text-xs">Approve</button>
|
|
693
|
+
<button data-run-review="deny" data-run-id="${r(u)}" data-run-family="${r(m)}" class="tcp-btn-danger h-7 px-2 text-xs">Deny</button>
|
|
694
|
+
</div>`:""}
|
|
695
|
+
<div class="mb-2 text-xs text-slate-300">${r(vt(x)||"No detail text available.")}</div>
|
|
696
|
+
<div class="mb-2 text-xs text-slate-400">Artifacts: ${z.length}</div>
|
|
697
|
+
${z.length?`<div class="mb-2 grid gap-1">${z.map(ae=>{const Pe=String(ae?.uri||"").trim(),Qe=String(ae?.kind||"artifact"),me=String(ae?.label||Qe).trim();return`<div class="text-xs text-slate-300"><span class="tcp-subtle">${r(Qe)}</span> <span class="font-mono">${r(me)}</span> ${Pe?`<span class="tcp-subtle">${r(Pe)}</span>`:""}</div>`}).join("")}</div>`:""}
|
|
698
|
+
<details class="mt-2">
|
|
699
|
+
<summary class="cursor-pointer text-xs text-slate-400">Raw run payload</summary>
|
|
700
|
+
<pre class="tcp-code mt-2">${r(JSON.stringify(x,null,2))}</pre>
|
|
701
|
+
</details>
|
|
702
|
+
</div>
|
|
703
|
+
`,En(Ot),o(Ot)}catch(x){s("err",x instanceof Error?x.message:String(x))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=y,o(a))}})),n("view").querySelectorAll("[data-run-automation]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.runAutomation||"").trim();if(!u){s("err","Automation ID is missing. Refresh and try again.");return}const m=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Running...',o(a);try{const y=await t.client.automations.runNow(u),x=String(y?.runId||"").trim(),R=String(y?.status||"").trim(),z=[];x&&z.push(`run ${x}`),R&&z.push(`status ${R}`),s("ok",z.length?`Automation triggered (${z.join(", ")}). It should move from queued to running within ~1 second.`:"Automation triggered."),setTimeout(()=>{et(e)},500)}catch(y){s("err",y instanceof Error?y.message:String(y))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=m,o(a))}})),n("view").querySelectorAll("[data-v2-run-now]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.v2RunNow||"").trim();if(!u)return;const m=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Running...',o(a);try{const y=await pt(R=>R.runNow(u)),x=String(y?.run?.run_id||y?.run?.runId||"").trim();s("ok",x?`Automation triggered (run ${x}).`:"Automation triggered."),setTimeout(()=>et(e),450)}catch(y){s("err",y instanceof Error?y.message:String(y))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=m,o(a))}})),n("view").querySelectorAll("[data-v2-toggle]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.v2Toggle||"").trim(),m=String(a.dataset.v2Next||"").trim().toLowerCase();if(!u)return;const y=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Saving...',o(a);try{m==="pause"?(await pt(x=>x.pause(u,"paused from control panel")),s("ok","Automation paused.")):(await pt(x=>x.resume(u)),s("ok","Automation resumed.")),setTimeout(()=>et(e),300)}catch(x){s("err",x instanceof Error?x.message:String(x))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=y,o(a))}})),n("view").querySelectorAll("[data-v2-runs]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.v2Runs||"").trim();if(!u)return;const m=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Loading',o(a);try{const y=await pt(z=>z.listRuns(u,20)),x=Array.isArray(y?.runs)?y.runs:[],R=x.map(z=>{const U=String(z?.run_id||z?.runId||"").trim(),J=String(z?.status||"unknown").toLowerCase(),te=Number(z?.updated_at_ms||z?.updatedAtMs||0);return`<div class="rounded-lg border border-slate-700/60 p-2">
|
|
704
|
+
<div class="flex items-center justify-between gap-2">
|
|
705
|
+
<span class="font-mono text-xs">${r(U||"run n/a")}</span>
|
|
706
|
+
<span class="${Be(J)}">${r(J)}</span>
|
|
707
|
+
</div>
|
|
708
|
+
<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
|
|
709
|
+
<span class="tcp-subtle">${r(ct(te))}</span>
|
|
710
|
+
${U?`<button data-v2-run-action="pause" data-v2-run-id="${r(U)}" class="tcp-btn h-7 px-2 text-xs">Pause</button>
|
|
711
|
+
<button data-v2-run-action="resume" data-v2-run-id="${r(U)}" class="tcp-btn h-7 px-2 text-xs">Resume</button>
|
|
712
|
+
<button data-v2-run-action="cancel" data-v2-run-id="${r(U)}" class="tcp-btn-danger h-7 px-2 text-xs">Cancel</button>`:""}
|
|
713
|
+
</div>
|
|
714
|
+
<details class="mt-1">
|
|
715
|
+
<summary class="cursor-pointer text-xs text-slate-400">Run payload</summary>
|
|
716
|
+
<pre class="tcp-code mt-1">${r(JSON.stringify(z,null,2))}</pre>
|
|
717
|
+
</details>
|
|
718
|
+
</div>`}).join("")||'<p class="tcp-subtle">No runs found for this automation.</p>';Kt.innerHTML=`<div class="tcp-list-item">
|
|
719
|
+
<div class="mb-2 flex items-center justify-between gap-2">
|
|
720
|
+
<span class="font-medium">Automation: ${r(u)}</span>
|
|
721
|
+
<span class="tcp-subtle">${x.length} runs</span>
|
|
722
|
+
</div>
|
|
723
|
+
<div class="grid gap-2">${R}</div>
|
|
724
|
+
</div>`,Kt.querySelectorAll("[data-v2-run-action]").forEach(z=>z.addEventListener("click",async()=>{const U=String(z.dataset.v2RunAction||"").trim(),J=String(z.dataset.v2RunId||"").trim();if(!J)return;const te=z.innerHTML;z.disabled=!0,z.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i>',o(z);try{U==="pause"?await pt(ee=>ee.pauseRun(J,"paused from control panel")):U==="resume"?await pt(ee=>ee.resumeRun(J,"resumed from control panel")):await pt(ee=>ee.cancelRun(J,"cancelled from control panel")),s("ok",`Run ${J} ${U} requested.`),setTimeout(()=>et(e),300)}catch(ee){s("err",ee instanceof Error?ee.message:String(ee))}finally{z.isConnected&&(z.disabled=!1,z.innerHTML=te,o(z))}})),o(Kt)}catch(y){s("err",y instanceof Error?y.message:String(y))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=m,o(a))}})),rt.querySelectorAll("[data-toggle-status]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.toggleStatus||"").trim(),m=String(a.dataset.nextStatus||"").trim();if(!u||!m){s("err","Routine status action is missing details. Refresh and try again.");return}const y=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Saving...',o(a);try{await t.client.routines.update(u,{status:m}),s("ok",`Routine ${m==="paused"?"paused":"resumed"}.`),et(e)}catch(x){s("err",x instanceof Error?x.message:String(x)),a.isConnected&&(a.disabled=!1,a.innerHTML=y,o(a))}})),rt.querySelectorAll("[data-run]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.run||"").trim();if(!u){s("err","Routine ID is missing. Refresh and try again.");return}const m=a.innerHTML;a.disabled=!0,a.innerHTML='<i data-lucide="refresh-cw" class="animate-spin"></i> Running...',o(a);try{const y=await t.client.routines.runNow(u),x=String(y?.runId||"").trim(),R=String(y?.status||"").trim(),z=[];x&&z.push(`run ${x}`),R&&z.push(`status ${R}`),s("ok",z.length?`Routine triggered (${z.join(", ")}). It should move from queued to running within ~1 second.`:"Routine triggered."),setTimeout(()=>{et(e)},500)}catch(y){s("err",y instanceof Error?y.message:String(y))}finally{a.isConnected&&(a.disabled=!1,a.innerHTML=m,o(a))}})),rt.querySelectorAll("[data-del]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.del||"").trim();if(!u){s("err","Routine ID is missing. Refresh and try again.");return}try{await t.client.routines.delete(u),s("ok","Routine deleted."),et(e)}catch(m){s("err",m instanceof Error?m.message:String(m))}})),rt.querySelectorAll("[data-edit-file]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.editFile||"").trim();if(u)try{const m=await i(`/api/files/read?path=${encodeURIComponent(u)}`);n("routine-use-file").checked=!0,n("routine-file-path").value=u,n("routine-prompt").value=String(m?.text||""),s("ok",`Loaded prompt file: ${u}`)}catch(m){s("err",m instanceof Error?m.message:String(m))}})),rt.querySelectorAll("[data-edit-routine]").forEach(a=>a.addEventListener("click",async()=>{const u=String(a.dataset.editRoutine||"").trim();if(!u){s("err","Routine ID is missing.");return}const m=Re.get(u);if(!m){s("err","Routine details not found. Refresh and try again.");return}jt.value=String(m.name||"").trim(),hc(m.schedule);const y=_e(m);if(y){Ws.checked=!0,Cn.value=y;try{const R=await i(`/api/files/read?path=${encodeURIComponent(y)}`);In.value=String(R?.text||"")}catch{In.value=String(m.entrypoint||""),s("err",`Could not read ${y}; loaded entrypoint text instead.`)}}else Ws.checked=!1,In.value=String(m.entrypoint||m.prompt||""),cs();Xe.value=He(m,"allowed_tools","allowedTools").join(", "),mt.checked=Se(m,"requires_approval","requiresApproval",!0),ft.checked=Se(m,"external_integrations_allowed","externalIntegrationsAllowed",!1);const x=fc(xe(Xe.value||""),!!mt.checked,!!ft.checked);Xs(x,{restore:!1}),ds(),gc(m),vc(u,String(m.name||"")),jt.focus()})),o(n("view"));const Ke=n("routine-schedule-mode"),rs=n("routine-interval-controls"),D=n("routine-daily-controls"),Q=n("routine-weekly-controls"),Y=n("routine-cron-controls"),Te=n("routine-interval-value"),Ie=n("routine-interval-unit"),wt=n("routine-time"),Me=n("routine-weekday"),We=n("routine-weekly-time"),At=n("routine-cron"),is=n("routine-schedule-preview"),jt=n("routine-name"),Ws=n("routine-use-file"),In=n("routine-prompt"),Cn=n("routine-file-path"),Rn=n("routine-model-provider"),_t=n("routine-model-id"),qt=n("routine-model-preview"),Ge=n("routine-allow-everything"),Xe=n("routine-allowed-tools"),Gs=n("routine-tool-scope-preview"),mt=n("routine-requires-approval"),ft=n("routine-external-integrations"),os=n("routine-form-mode"),Mn=n("cancel-edit-routine"),as=n("create-routine");let Pn="";const cs=()=>{const a=`control-panel/routines/${ue(jt.value||"new-routine")}.md`,m=String(Cn.value||"").trim().replace(/\\/g,"/").replace(/^\/+/,"")||a,y=m==="control-panel"||m.startsWith("control-panel/")?m:`control-panel/${m}`;Cn.value=y.endsWith(".md")?y:`${y}.md`},mc=a=>{const u=xt(a);if(!u.length)return"";const m=String(nt[a]||"").trim();return m&&u.includes(m)?m:u[0]},ls=()=>{const a=String(Rn?.value||"").trim(),u=xt(a);if(!_t)return;if(_t.innerHTML=u.map(x=>`<option value="${r(x)}">${r(x)}</option>`).join("")||'<option value="">No models found</option>',!u.length){_t.disabled=!0,qt&&(qt.textContent="default engine route");return}_t.disabled=!1;const m=mc(a);m&&(_t.value=m);const y=String(_t.value||"").trim();qt&&(qt.textContent=a&&y?`${a}/${y}`:"default engine route")},ds=()=>{const a=xe(Xe?.value||"");if(Gs){if(Ge?.checked){Gs.textContent="Tool scope: unrestricted (all tools + external integrations, no approval gate)";return}Gs.textContent=a.length?`Tool scope: allowlist (${a.length})`:"Tool scope: all tools allowed by policy"}},fc=(a,u,m)=>!u&&m&&a.length===0,Xs=(a,{restore:u=!0}={})=>{Ge&&(Ge.checked=!!a,a?(Ge.dataset.prevTools=String(Xe?.value||""),Ge.dataset.prevRequiresApproval=mt?.checked?"1":"0",Ge.dataset.prevExternalIntegrations=ft?.checked?"1":"0",Xe&&(Xe.value="",Xe.disabled=!0),mt&&(mt.checked=!1,mt.disabled=!0),ft&&(ft.checked=!0,ft.disabled=!0)):(Xe&&(Xe.disabled=!1),mt&&(mt.disabled=!1),ft&&(ft.disabled=!1),u&&(Xe&&(Xe.value=String(Ge.dataset.prevTools||"")),mt&&(mt.checked=String(Ge.dataset.prevRequiresApproval||"1")==="1"),ft&&(ft.checked=String(Ge.dataset.prevExternalIntegrations||"0")==="1"))),ds())},hc=a=>{const u=Number(a?.interval_seconds?.seconds??a?.intervalSeconds?.seconds??a?.intervalSeconds??0),m=String(a?.cron?.expression??a?.cron?.cron??a?.expression??a?.cron??"").trim();if(u>0){u%3600===0?(Ke.value="interval",Ie.value="hours",Te.value=String(Math.max(1,Math.floor(u/3600)))):(Ke.value="interval",Ie.value="minutes",Te.value=String(Math.max(1,Math.floor(u/60)))),Ye();return}if(!m){Ke.value="manual",Ye();return}const y=m.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+\*$/);if(y){Ke.value="daily";const R=String(Number.parseInt(y[1],10)).padStart(2,"0"),z=String(Number.parseInt(y[2],10)).padStart(2,"0");wt.value=`${z}:${R}`,Ye();return}const x=m.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-6])$/);if(x){Ke.value="weekly";const R=String(Number.parseInt(x[1],10)).padStart(2,"0"),z=String(Number.parseInt(x[2],10)).padStart(2,"0");Me.value=String(Number.parseInt(x[3],10)),We.value=`${z}:${R}`,Ye();return}Ke.value="customCron",At.value=m,Ye()},gc=a=>{const u=String(a?.args?.model_policy?.default_model?.provider_id||"").trim(),m=String(a?.args?.model_policy?.default_model?.model_id||"").trim();if(!u||!dt.includes(u)){ls();return}Rn.value=u,ls();const y=xt(u);m&&y.includes(m)&&(_t.value=m,qt&&(qt.textContent=`${u}/${m}`))},vc=(a,u="")=>{Pn=a,os&&(os.textContent=`Editing routine ${u||a}`),as&&(as.innerHTML='<i data-lucide="save"></i> Save Changes'),Mn&&Mn.classList.remove("hidden"),o(n("view"))},yc=()=>{Pn="",os&&(os.textContent="Creating new routine"),as&&(as.innerHTML='<i data-lucide="plus"></i> Create'),Mn&&Mn.classList.add("hidden"),o(n("view"))},ai=()=>{const a=String(Ke.value||"interval");if(a==="interval"){const m=Number.parseInt(String(Te.value||"30"),10),y=Number.isFinite(m)?m:30;if(y<=0)throw new Error("Interval must be at least 1.");const R=String(Ie.value||"minutes")==="hours"?3600:60;return{interval_seconds:{seconds:y*R}}}if(a==="manual")return{interval_seconds:{seconds:24*3600}};if(a==="daily"){const[m,y]=String(wt.value||"09:00").split(":").map(z=>Number.parseInt(z,10)),x=Number.isFinite(m)?Math.min(23,Math.max(0,m)):9;return{cron:{expression:`${Number.isFinite(y)?Math.min(59,Math.max(0,y)):0} ${x} * * *`}}}if(a==="weekly"){const[m,y]=String(We.value||"09:00").split(":").map(J=>Number.parseInt(J,10)),x=Number.isFinite(m)?Math.min(23,Math.max(0,m)):9,R=Number.isFinite(y)?Math.min(59,Math.max(0,y)):0,z=Number.parseInt(String(Me.value||"1"),10),U=Number.isFinite(z)?Math.min(6,Math.max(0,z)):1;return{cron:{expression:`${R} ${x} * * ${U}`}}}const u=String(At.value||"").trim();if(!u)throw new Error("Custom cron is required.");return{cron:{expression:u}}},bc=()=>{const a=String(Ke.value||"interval");if(a==="interval"){const m=Number.parseInt(String(Te.value||"30"),10),y=String(Ie.value||"minutes");return`every ${Number.isFinite(m)&&m>0?m:30}${y==="hours"?"h":"m"}`}if(a==="daily")return`daily at ${String(wt.value||"09:00")}`;if(a==="weekly"){const m={0:"Sunday",1:"Monday",2:"Tuesday",3:"Wednesday",4:"Thursday",5:"Friday",6:"Saturday"},y=Number.parseInt(String(Me.value||"1"),10);return`weekly on ${m[y]||"Monday"} at ${String(We.value||"09:00")}`}if(a==="manual")return"manual";const u=String(At.value||"").trim();return u?`cron ${u}`:"custom cron (required)"},Ye=()=>{const a=String(Ke.value||"interval"),u=a==="interval",m=a==="daily",y=a==="weekly",x=a==="customCron";rs.classList.toggle("hidden",!u),D.classList.toggle("hidden",!m),Q.classList.toggle("hidden",!y),Y.classList.toggle("hidden",!x),At.classList.toggle("hidden",!x);try{const R=ai();is.textContent=`Schedule: ${bc()} (${ie(R)})`}catch(R){is.textContent=`Schedule: ${R instanceof Error?R.message:String(R)}`}},ci=async()=>{cs();const a=String(Cn.value||"").trim(),u=String(In.value||"");if(!a||!u.trim())throw new Error("Prompt file path and content are required.");return await i("/api/files/write",{method:"POST",body:JSON.stringify({path:a,text:u,overwrite:!0})}),a};n("save-routine-file").addEventListener("click",async()=>{try{const a=await ci();s("ok",`Saved ${a}`)}catch(a){s("err",a instanceof Error?a.message:String(a))}}),jt.addEventListener("input",()=>{const a=String(Cn.value||"").trim();(!a||/new-routine\.md$/i.test(a))&&cs()}),Ke.addEventListener("change",Ye),Te.addEventListener("input",Ye),Ie.addEventListener("change",Ye),wt.addEventListener("input",Ye),Me.addEventListener("change",Ye),We.addEventListener("input",Ye),At.addEventListener("input",Ye),Rn?.addEventListener("change",()=>{ls()}),_t?.addEventListener("change",()=>{const a=String(Rn?.value||"").trim(),u=String(_t?.value||"").trim();qt&&(qt.textContent=a&&u?`${a}/${u}`:"default engine route")}),Ge?.addEventListener("change",()=>{Xs(!!Ge.checked,{restore:!0})}),Xe?.addEventListener("input",ds),Mn?.addEventListener("click",()=>{et(e)}),Ye(),cs(),ls(),Xs(!!Ge?.checked,{restore:!1}),ds(),yc(),n("create-routine").addEventListener("click",async()=>{try{const a=String(jt.value||"").trim(),u=String(In.value||"").trim();if(!a||!u)throw new Error("Name and prompt are required.");const m=ai(),y=String(Ke.value||"")==="manual";let x=u,R="";Ws.checked&&(R=await ci(),x=[`Use the routine prompt markdown at: ${R}`,"Read the file first, then execute its instructions exactly."].join(`
|
|
725
|
+
`));const z={};R&&(z.promptFilePath=R);const U=String(Rn?.value||"").trim(),J=String(_t?.value||"").trim();U&&J&&(z.model_policy={default_model:{provider_id:U,model_id:J}});const te=!!Ge?.checked,ee=te?[]:xe(Xe?.value||""),ae=te?!1:!!mt?.checked,Pe=te?!0:!!ft?.checked;if(Pn){const Qe=Re.get(Pn),me={name:a,entrypoint:x,schedule:m,args:z,allowed_tools:ee,requires_approval:ae,external_integrations_allowed:Pe};y?me.status="paused":Qe?.status&&(me.status=String(Qe.status).toLowerCase()),await t.client.routines.update(Pn,me),s("ok","Routine updated.")}else{const Qe=await t.client.routines.create({name:a,entrypoint:x,schedule:m,args:z,allowed_tools:ee,requires_approval:ae,external_integrations_allowed:Pe});if(y){const me=Ae(Qe?.routine||Qe||{});me&&await t.client.routines.update(me,{status:"paused"})}s("ok","Routine created.")}et(e)}catch(a){s("err",a instanceof Error?a.message:String(a))}})}async function Ar(e){const{state:t,byId:n,toast:s,escapeHtml:r,api:i}=e,[o,c]=await Promise.all([t.client.channels.status().catch(()=>({})),t.client.channels.config().catch(()=>({}))]),l=["telegram","discord","slack"],d=(h,_,A,$=void 0)=>!h||typeof h!="object"?$:h[_]!==void 0?h[_]:h[A]!==void 0?h[A]:$,p=h=>Array.isArray(h)&&h.length?h.join(", "):"*",f=!!d(c.discord||{},"has_token","hasToken",!1);n("view").innerHTML=`
|
|
726
|
+
<div class="tcp-card">
|
|
727
|
+
<div class="mb-3 flex items-center justify-between">
|
|
728
|
+
<h3 class="tcp-title">Channels</h3>
|
|
729
|
+
<i data-lucide="messages-square"></i>
|
|
730
|
+
</div>
|
|
731
|
+
${f?"":`<div class="mb-3 rounded-lg border border-amber-500/30 bg-amber-500/10 p-3 text-sm text-amber-100">
|
|
732
|
+
<div class="font-semibold">Discord Quick Setup</div>
|
|
733
|
+
<div class="mt-1">1) Create bot and copy token. 2) Enable Message Content Intent. 3) Invite bot with channel send/read permissions. 4) Save then click Verify Discord.</div>
|
|
734
|
+
</div>`}
|
|
735
|
+
<div id="channels-list" class="tcp-list"></div>
|
|
736
|
+
</div>
|
|
737
|
+
`;const b=n("channels-list");b.innerHTML=l.map(h=>{const _=o[h]||{},A=d(_,"last_error","lastError","");return`
|
|
738
|
+
<div class="tcp-list-item">
|
|
739
|
+
<div class="mb-3 flex items-center justify-between">
|
|
740
|
+
<strong class="capitalize">${h}</strong>
|
|
741
|
+
<span class="${_.connected?"tcp-badge-ok":"tcp-badge-warn"}">${_.connected?"connected":"not connected"}</span>
|
|
742
|
+
</div>
|
|
743
|
+
<div class="grid gap-3 lg:grid-cols-4">
|
|
744
|
+
<input id="${h}-token" class="tcp-input" placeholder="bot token" />
|
|
745
|
+
<input id="${h}-users" class="tcp-input" placeholder="allowed users (comma, * for all)" />
|
|
746
|
+
${h==="discord"?`<input id="${h}-guild" class="tcp-input" placeholder="guild id (optional)" />`:h==="slack"?`<input id="${h}-channel" class="tcp-input" placeholder="channel id (required for slack)" />`:`<select id="${h}-style" class="tcp-select">
|
|
747
|
+
<option value="default">style: default</option>
|
|
748
|
+
<option value="compact">style: compact</option>
|
|
749
|
+
<option value="friendly">style: friendly</option>
|
|
750
|
+
<option value="ops">style: ops</option>
|
|
751
|
+
</select>`}
|
|
752
|
+
<div class="flex gap-2">
|
|
753
|
+
<button class="tcp-btn-primary" data-save="${h}"><i data-lucide="save"></i> Save</button>
|
|
754
|
+
${h==="discord"?`<button class="tcp-btn" data-verify="${h}">Verify Discord</button>`:""}
|
|
755
|
+
<button class="tcp-btn-danger" data-del="${h}"><i data-lucide="trash-2"></i></button>
|
|
756
|
+
</div>
|
|
757
|
+
</div>
|
|
758
|
+
<div class="mt-2 flex flex-wrap items-center gap-3 text-xs text-slate-400">
|
|
759
|
+
${h==="telegram"||h==="discord"?`<label class="inline-flex items-center gap-2"><input id="${h}-mention" type="checkbox" /> mention only</label>`:""}
|
|
760
|
+
${h==="discord"?"<span>Tip: use <code>@bot /help</code> style commands (Discord app slash commands are not registered).</span>":""}
|
|
761
|
+
</div>
|
|
762
|
+
${h==="discord"?`<div id="${h}-verify-result" class="mt-2 text-xs text-slate-300"></div>`:""}
|
|
763
|
+
${A?`<div class="mt-2 text-xs text-rose-300">last error: ${r(String(A))}</div>`:""}
|
|
764
|
+
</div>
|
|
765
|
+
`}).join(""),l.forEach(h=>{const _=c[h]||{},A=d(_,"allowed_users","allowedUsers",["*"]),$=!!d(_,"mention_only","mentionOnly",h==="discord"),O=d(_,"guild_id","guildId",""),V=d(_,"channel_id","channelId",""),T=String(d(_,"style_profile","styleProfile","default")||"default"),S=!!d(_,"has_token","hasToken",!1),M=n(`${h}-token`);M&&S&&(M.placeholder="token configured (leave blank to keep)");const C=n(`${h}-users`);C&&(C.value=p(A));const I=n(`${h}-mention`);I&&(I.checked=$);const L=n(`${h}-guild`);L&&(L.value=O||"");const P=n(`${h}-channel`);P&&(P.value=V||"");const K=n(`${h}-style`);K&&(K.value=T)});const w=h=>{const _=n(`${h}-token`).value.trim(),A=n(`${h}-users`).value.trim(),$={bot_token:_,allowed_users:A?A.split(",").map(O=>O.trim()).filter(Boolean):["*"]};return(h==="telegram"||h==="discord")&&($.mention_only=!!n(`${h}-mention`)?.checked),h==="telegram"&&($.style_profile=String(n(`${h}-style`)?.value||"default")),h==="discord"&&($.guild_id=n(`${h}-guild`)?.value?.trim()||null),h==="slack"&&($.channel_id=n(`${h}-channel`)?.value?.trim()||null),$};b.querySelectorAll("[data-save]").forEach(h=>h.addEventListener("click",async()=>{const _=h.dataset.save,A=w(_);try{await t.client.channels.put(_,A),s("ok",`${_} saved.`),Ar(e)}catch($){s("err",$ instanceof Error?$.message:String($))}})),b.querySelectorAll("[data-verify]").forEach(h=>h.addEventListener("click",async()=>{const _=h.dataset.verify,A=n(`${_}-verify-result`);A&&(A.className="mt-2 text-xs text-slate-300",A.textContent="Verifying Discord configuration...");try{const $=await i(`/api/engine/channels/${encodeURIComponent(_)}/verify`,{method:"POST",body:JSON.stringify(w(_))}),O=d($,"checks","checks",{}),V=d($,"hints","hints",[]),T=!!d($,"ok","ok",!1),S=!!d(O,"token_auth_ok","tokenAuthOk",!1),M=!!d(O,"gateway_ok","gatewayOk",!1),C=!!d(O,"message_content_intent_ok","messageContentIntentOk",!1),I=Array.isArray(V)&&V.length>0?String(V[0]):"",L=T?"Verification passed: token/auth, gateway, and Message Content intent are OK.":`Verification failed: token=${S?"ok":"fail"}, gateway=${M?"ok":"fail"}, message_intent=${C?"ok":"fail"}. ${I}`;A&&(A.className=`mt-2 text-xs ${T?"text-emerald-300":"text-amber-200"}`,A.innerHTML=r(L)),s(T?"ok":"warn",T?"Discord verify passed.":"Discord verify failed.")}catch($){const O=$ instanceof Error?$.message:String($);A&&(A.className="mt-2 text-xs text-rose-300",A.textContent=`Verify request failed: ${O}`),s("err",O)}})),b.querySelectorAll("[data-del]").forEach(h=>h.addEventListener("click",async()=>{const _=h.dataset.del;try{await t.client.channels.delete(_),s("ok",`${_} deleted.`),Ar(e)}catch(A){s("err",A instanceof Error?A.message:String(A))}}))}function ni(e){try{return new URL(e)}catch{return null}}function tc(e){return String(e||"").trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")||"mcp-server"}function co(e){const t=ni(e);if(!t)return"";const n=String(t.hostname||"").toLowerCase();if(!n)return"";if(n.endsWith("composio.dev"))return"composio";const s=n.split(".").filter(Boolean);if(s.length===0)return"";const r=["backend","api","mcp","www"].includes(s[0])&&s[1]||s[0];return tc(r)}function si(e){const t=ni(e);return t?String(t.hostname||"").toLowerCase().endsWith("composio.dev"):!1}function cr(e,t=""){if(!e||typeof e!="object")return null;const n=e,s=String(n.name||t||"").trim();return s?{name:s,transport:String(n.transport||"").trim(),connected:!!n.connected,enabled:n.enabled!==!1,lastError:String(n.last_error||n.lastError||"").trim(),headers:n.headers&&typeof n.headers=="object"?n.headers:{},toolCache:Array.isArray(n.tool_cache||n.toolCache)?n.tool_cache||n.toolCache:[]}:null}function lo(e){return Array.isArray(e)?e.map(t=>cr(t)).filter(Boolean).sort((t,n)=>t.name.localeCompare(n.name)):!e||typeof e!="object"?[]:Array.isArray(e.servers)?e.servers.map(t=>cr(t)).filter(Boolean).sort((t,n)=>t.name.localeCompare(n.name)):Object.entries(e).map(([t,n])=>cr(n&&typeof n=="object"?n:{transport:String(n||"")},t)).filter(Boolean).sort((t,n)=>t.name.localeCompare(n.name))}function Bg(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?t:!t||typeof t!="object"?"":String(t.namespaced_name||t.namespacedName||t.id||t.tool_name||t.toolName||"").trim()).filter(Boolean):[]}function Jg(e,t,n,s){return!!!String(t||"").trim()||e==="none"?"No auth header will be sent.":e==="custom"?n?`Header preview: ${n}: <token>`:"Set a custom header name.":e==="x-api-key"?"Header preview: x-api-key: <token>":e==="bearer"?"Header preview: Authorization: Bearer <token>":si(s)?"Auto mode: detected Composio URL -> x-api-key":"Auto mode: using Authorization Bearer token"}function Kg({authMode:e,token:t,customHeader:n,transport:s}){const r=String(t||"").trim();if(!r||e==="none")return{};if(e==="custom"){const o=String(n||"").trim();if(!o)throw new Error("Custom header name is required.");return{[o]:r}}return e==="x-api-key"?{"x-api-key":r}:e==="bearer"?{Authorization:`Bearer ${r.replace(/^bearer\s+/i,"").trim()}`}:si(s)?{"x-api-key":r}:{Authorization:`Bearer ${r.replace(/^bearer\s+/i,"").trim()}`}}async function Dn(e){const{state:t,byId:n,api:s,toast:r,escapeHtml:i}=e,[o,c]=await Promise.all([t.client.mcp.list().catch(()=>({})),t.client.mcp.listTools().catch(()=>[])]),l=lo(o),d=Bg(c);n("view").innerHTML=`
|
|
766
|
+
<div class="grid gap-4 xl:grid-cols-[440px_1fr]">
|
|
767
|
+
<div class="tcp-card">
|
|
768
|
+
<h3 class="tcp-title mb-2">Add MCP Server</h3>
|
|
769
|
+
<p class="tcp-subtle mb-3">Paste your MCP endpoint URL and token. For Composio URLs, Auto auth uses <code>x-api-key</code>.</p>
|
|
770
|
+
<div class="grid gap-3">
|
|
771
|
+
<div>
|
|
772
|
+
<label class="mb-1 block text-sm text-slate-300">Name</label>
|
|
773
|
+
<input id="mcp-name" class="tcp-input" placeholder="composio" value="composio" />
|
|
774
|
+
</div>
|
|
775
|
+
<div>
|
|
776
|
+
<label class="mb-1 block text-sm text-slate-300">Transport URL</label>
|
|
777
|
+
<input id="mcp-transport" class="tcp-input" placeholder="https://backend.composio.dev/.../mcp?user_id=..." />
|
|
778
|
+
</div>
|
|
779
|
+
<div>
|
|
780
|
+
<label class="mb-1 block text-sm text-slate-300">Auth Mode</label>
|
|
781
|
+
<select id="mcp-auth-mode" class="tcp-select">
|
|
782
|
+
<option value="auto" selected>Auto (Composio => x-api-key, else Bearer)</option>
|
|
783
|
+
<option value="x-api-key">x-api-key</option>
|
|
784
|
+
<option value="bearer">Authorization Bearer</option>
|
|
785
|
+
<option value="custom">Custom Header</option>
|
|
786
|
+
<option value="none">No Auth Header</option>
|
|
787
|
+
</select>
|
|
788
|
+
</div>
|
|
789
|
+
<div id="mcp-custom-header-wrap" class="hidden">
|
|
790
|
+
<label class="mb-1 block text-sm text-slate-300">Custom Header Name</label>
|
|
791
|
+
<input id="mcp-custom-header" class="tcp-input" placeholder="X-My-Token" />
|
|
792
|
+
</div>
|
|
793
|
+
<div>
|
|
794
|
+
<label class="mb-1 block text-sm text-slate-300">Token (optional)</label>
|
|
795
|
+
<input id="mcp-token" class="tcp-input" type="password" placeholder="token" />
|
|
796
|
+
</div>
|
|
797
|
+
<p id="mcp-auth-preview" class="tcp-subtle"></p>
|
|
798
|
+
<button id="mcp-add" class="tcp-btn-primary"><i data-lucide="plug-zap"></i> Add + Connect</button>
|
|
799
|
+
</div>
|
|
800
|
+
</div>
|
|
801
|
+
|
|
802
|
+
<div class="grid gap-4">
|
|
803
|
+
<div class="tcp-card">
|
|
804
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
805
|
+
<h3 class="tcp-title">Servers (${l.length})</h3>
|
|
806
|
+
<button id="mcp-refresh-all" class="tcp-btn"><i data-lucide="refresh-cw"></i> Reload</button>
|
|
807
|
+
</div>
|
|
808
|
+
<div id="mcp-servers" class="tcp-list"></div>
|
|
809
|
+
</div>
|
|
810
|
+
|
|
811
|
+
<div class="tcp-card">
|
|
812
|
+
<h3 class="tcp-title mb-3">Discovered MCP Tools (${d.length})</h3>
|
|
813
|
+
<pre class="tcp-code max-h-[320px] overflow-auto">${i(d.slice(0,350).join(`
|
|
814
|
+
`))||"No tools discovered yet. Connect a server first."}</pre>
|
|
815
|
+
</div>
|
|
816
|
+
</div>
|
|
817
|
+
</div>
|
|
818
|
+
`;const p=n("mcp-name"),f=n("mcp-transport"),b=n("mcp-token"),w=n("mcp-auth-mode"),h=n("mcp-custom-header-wrap"),_=n("mcp-custom-header"),A=n("mcp-auth-preview"),$=()=>{const T=w.value;h.classList.toggle("hidden",T!=="custom"),A.textContent=Jg(T,b.value,_.value,f.value)},O=()=>{const T=String(p.value||"").trim();if(!T||T==="composio"||T==="mcp-server"){const S=co(f.value.trim());S&&(p.value=S)}};f.addEventListener("input",()=>{O(),$()}),b.addEventListener("input",$),w.addEventListener("change",$),_.addEventListener("input",$),$(),n("mcp-add").addEventListener("click",async()=>{const T=String(f.value||"").trim(),S=tc(p.value||co(T)),M=String(w.value||"auto"),C=b.value,I=_.value;if(!T)return r("err","Transport URL is required.");if(!ni(T)&&!T.startsWith("stdio:"))return r("err","Transport must be a valid URL or stdio:* transport.");try{const L=Kg({authMode:M,token:C,customHeader:I,transport:T}),P={name:S,transport:T,enabled:!0};if(Object.keys(L).length&&(P.headers=L),await t.client.mcp.add(P),!(await t.client.mcp.connect(S))?.ok){const G=lo(await t.client.mcp.list().catch(()=>({}))).find(he=>he.name===S),gt=G?.lastError?` ${G.lastError}`:"",St=si(T)&&/401|403|unauthorized|forbidden|invalid api key|api key/i.test(gt)?" Composio usually expects `x-api-key` and a valid `user_id` query param.":"";throw new Error(`Unable to connect MCP server "${S}".${gt}${St}`)}r("ok",`MCP "${S}" connected.`),await Dn(e)}catch(L){r("err",L instanceof Error?L.message:String(L)),await Dn(e)}}),n("mcp-refresh-all").addEventListener("click",()=>{Dn(e)});const V=n("mcp-servers");V.innerHTML=l.map(T=>{const S=Object.keys(T.headers||{}).filter(Boolean),M=Array.isArray(T.toolCache)?T.toolCache.length:0;return`
|
|
819
|
+
<div class="tcp-list-item grid gap-2">
|
|
820
|
+
<div class="flex flex-wrap items-center justify-between gap-2">
|
|
821
|
+
<div>
|
|
822
|
+
<div class="font-semibold">${i(T.name)}</div>
|
|
823
|
+
<div class="tcp-subtle">${i(T.transport||"No transport set")}</div>
|
|
824
|
+
</div>
|
|
825
|
+
<div class="flex flex-wrap gap-2">
|
|
826
|
+
<span class="${T.connected?"tcp-badge-ok":"tcp-badge-warn"}">${T.connected?"Connected":"Disconnected"}</span>
|
|
827
|
+
<span class="${T.enabled?"tcp-badge-info":"tcp-badge-warn"}">${T.enabled?"Enabled":"Disabled"}</span>
|
|
828
|
+
<span class="tcp-badge-info">Tools: ${M}</span>
|
|
829
|
+
</div>
|
|
830
|
+
</div>
|
|
831
|
+
${T.lastError?`<div class="rounded-xl border border-rose-700/60 bg-rose-950/20 px-2 py-1 text-xs text-rose-300">${i(T.lastError)}</div>`:""}
|
|
832
|
+
${S.length?`<div class="tcp-subtle text-xs">Auth headers: ${i(S.join(", "))}</div>`:'<div class="tcp-subtle text-xs">No stored auth headers.</div>'}
|
|
833
|
+
<div class="flex flex-wrap gap-2">
|
|
834
|
+
<button class="tcp-btn" data-action="${T.connected?"disconnect":"connect"}" data-name="${encodeURIComponent(T.name)}">
|
|
835
|
+
${T.connected?"Disconnect":"Connect"}
|
|
836
|
+
</button>
|
|
837
|
+
<button class="tcp-btn" data-action="refresh" data-name="${encodeURIComponent(T.name)}">Refresh</button>
|
|
838
|
+
<button class="tcp-btn" data-action="toggle-enabled" data-name="${encodeURIComponent(T.name)}" data-enabled="${T.enabled?"1":"0"}">
|
|
839
|
+
${T.enabled?"Disable":"Enable"}
|
|
840
|
+
</button>
|
|
841
|
+
<button class="tcp-btn-danger" data-action="delete" data-name="${encodeURIComponent(T.name)}">Delete</button>
|
|
842
|
+
</div>
|
|
843
|
+
</div>
|
|
844
|
+
`}).join("")||'<p class="tcp-subtle">No MCP servers configured.</p>',V.querySelectorAll("button[data-action]").forEach(T=>{T.addEventListener("click",async()=>{const S=String(T.dataset.action||""),M=String(T.dataset.name||""),C=M?decodeURIComponent(M):"";if(C)try{if(S==="connect")await t.client.mcp.connect(C),r("ok",`Connected ${C}.`);else if(S==="disconnect")await t.client.mcp.disconnect(C),r("ok",`Disconnected ${C}.`);else if(S==="refresh")await t.client.mcp.refresh(C),r("ok",`Refreshed ${C}.`);else if(S==="toggle-enabled"){const I=String(T.dataset.enabled||"0")==="1";await t.client.mcp.setEnabled(C,!I),r("ok",`${I?"Disabled":"Enabled"} ${C}.`)}else S==="delete"&&(await s(`/api/engine/mcp/${encodeURIComponent(C)}`,{method:"DELETE"}),r("ok",`Deleted ${C}.`));await Dn(e)}catch(I){r("err",I instanceof Error?I.message:String(I))}})})}function lr(e){const t=String(e||"").toLowerCase();return t.includes("fail")||t.includes("error")?"tcp-badge-err":t.includes("wait")||t.includes("queue")||t.includes("new")?"tcp-badge-warn":"tcp-badge-ok"}function Wg(e){const t=new Map;for(const n of e){const s=n.ownerRole||"unknown",r=t.get(s)||{total:0,running:0,done:0,failed:0};r.total+=1;const i=String(n.status||"").toLowerCase();i.includes("fail")||i.includes("error")?r.failed+=1:i.includes("done")||i.includes("complete")?r.done+=1:r.running+=1,t.set(s,r)}return[...t.entries()]}function Gg(e){return e?e.kind==="task_transition"?`${e.taskId}: ${e.from} -> ${e.to} (${e.reason||"status changed"})`:e.kind==="task_reason"?`${e.taskId}: ${e.reason||"updated"}`:e.reason||JSON.stringify(e):""}async function jn(e){const{api:t,byId:n,escapeHtml:s,toast:r,state:i,addCleanup:o}=e;if(i.route!=="swarm")return;const c=i.route;if(i.__swarmLiveCleanup&&Array.isArray(i.__swarmLiveCleanup))for(const $ of i.__swarmLiveCleanup)try{$()}catch{}i.__swarmLiveCleanup=[];const l=await t("/api/swarm/status").catch(()=>({status:"error"})),d=await t("/api/swarm/snapshot").catch(()=>({registry:{value:{tasks:{}}},logs:[],reasons:[]}));if(i.route!==c)return;const p=Object.values(d.registry?.value?.tasks||{}),f=(d.reasons||[]).slice().reverse(),b=Wg(p);n("view").innerHTML=`
|
|
845
|
+
<div class="tcp-card">
|
|
846
|
+
<div class="mb-3 flex items-center justify-between gap-3">
|
|
847
|
+
<h3 class="tcp-title flex items-center gap-2"><i data-lucide="cpu"></i> Node Swarm Orchestrator</h3>
|
|
848
|
+
<span class="${lr(l.status)}">${s(l.status||"idle")}</span>
|
|
849
|
+
</div>
|
|
850
|
+
<p class="mb-3 rounded-xl border border-slate-700/60 bg-slate-900/25 px-3 py-2 text-xs text-slate-300">
|
|
851
|
+
Swarm is best for short-lived interactive orchestration. For persistent scheduled multi-agent pipelines, use <strong>Automations</strong>.
|
|
852
|
+
</p>
|
|
853
|
+
<div class="grid gap-3 md:grid-cols-[1fr_1fr_120px_auto]">
|
|
854
|
+
<input id="swarm-root" class="tcp-input" value="${s(l.workspaceRoot||"")}" placeholder="workspace root" />
|
|
855
|
+
<input id="swarm-objective" class="tcp-input" value="${s(l.objective||"Ship a small feature end-to-end")}" placeholder="objective" />
|
|
856
|
+
<input id="swarm-max" class="tcp-input" type="number" min="1" value="${s(String(l.maxTasks||3))}" />
|
|
857
|
+
<div class="flex gap-2">
|
|
858
|
+
<button id="swarm-start" class="tcp-btn-primary" ${l.localEngine?"":"disabled"}><i data-lucide="play"></i> Start</button>
|
|
859
|
+
<button id="swarm-stop" class="tcp-btn-danger"><i data-lucide="square"></i> Stop</button>
|
|
860
|
+
</div>
|
|
861
|
+
</div>
|
|
862
|
+
${l.localEngine?"":'<p class="mt-3 rounded-xl border border-amber-700/60 bg-amber-950/20 px-3 py-2 text-sm text-amber-300">Swarm orchestration is disabled on remote engine URLs. Monitoring remains available.</p>'}
|
|
863
|
+
</div>
|
|
864
|
+
|
|
865
|
+
<div class="tcp-card">
|
|
866
|
+
<h3 class="tcp-title mb-3">Live Agent Flow</h3>
|
|
867
|
+
<div class="overflow-hidden rounded-xl border border-slate-700 bg-black/20 p-2">
|
|
868
|
+
<svg viewBox="0 0 680 240" class="h-[280px] w-full">
|
|
869
|
+
<defs>
|
|
870
|
+
<linearGradient id="wire-grad" x1="0" y1="0" x2="1" y2="0">
|
|
871
|
+
<stop offset="0%" stop-color="#64748b" stop-opacity="0.12"></stop>
|
|
872
|
+
<stop offset="50%" stop-color="#94a3b8" stop-opacity="0.95"></stop>
|
|
873
|
+
<stop offset="100%" stop-color="#64748b" stop-opacity="0.12"></stop>
|
|
874
|
+
</linearGradient>
|
|
875
|
+
</defs>
|
|
876
|
+
<line x1="140" y1="120" x2="320" y2="60" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
877
|
+
<line x1="140" y1="120" x2="320" y2="120" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
878
|
+
<line x1="140" y1="120" x2="320" y2="180" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
879
|
+
<line x1="360" y1="60" x2="540" y2="50" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
880
|
+
<line x1="360" y1="120" x2="540" y2="120" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
881
|
+
<line x1="360" y1="180" x2="540" y2="190" stroke="url(#wire-grad)" stroke-width="2" class="wire-line-active"></line>
|
|
882
|
+
|
|
883
|
+
<circle cx="120" cy="120" r="20" fill="rgba(30,41,59,0.95)" stroke="rgba(148,163,184,0.8)" stroke-width="1.5" class="node-active"></circle>
|
|
884
|
+
<text x="120" y="152" text-anchor="middle" fill="#cbd5e1" font-size="11">Manager</text>
|
|
885
|
+
<circle cx="340" cy="60" r="18" fill="rgba(30,41,59,0.95)" stroke="rgba(148,163,184,0.7)" stroke-width="1.5" class="node-active"></circle>
|
|
886
|
+
<text x="340" y="92" text-anchor="middle" fill="#cbd5e1" font-size="11">Worker</text>
|
|
887
|
+
<circle cx="340" cy="120" r="18" fill="rgba(30,41,59,0.95)" stroke="rgba(148,163,184,0.7)" stroke-width="1.5" class="node-active"></circle>
|
|
888
|
+
<text x="340" y="152" text-anchor="middle" fill="#cbd5e1" font-size="11">Tester</text>
|
|
889
|
+
<circle cx="340" cy="180" r="18" fill="rgba(30,41,59,0.95)" stroke="rgba(148,163,184,0.7)" stroke-width="1.5" class="node-active"></circle>
|
|
890
|
+
<text x="340" y="212" text-anchor="middle" fill="#cbd5e1" font-size="11">Reviewer</text>
|
|
891
|
+
</svg>
|
|
892
|
+
</div>
|
|
893
|
+
<div class="mt-3 grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
|
894
|
+
${b.map(([$,O])=>`<div class="tcp-list-item"><div class="font-medium">${s($)}</div><div class="tcp-subtle mt-1">${O.total} tasks</div><div class="text-xs text-slate-400">${O.running} active / ${O.done} done / ${O.failed} failed</div></div>`).join("")||'<p class="tcp-subtle">No active roles yet.</p>'}
|
|
895
|
+
</div>
|
|
896
|
+
</div>
|
|
897
|
+
|
|
898
|
+
<div class="tcp-card">
|
|
899
|
+
<div class="mb-3 flex items-center justify-between gap-2">
|
|
900
|
+
<h3 class="tcp-title">Swarm Why Timeline</h3>
|
|
901
|
+
<div class="flex gap-2">
|
|
902
|
+
<select id="swarm-reason-kind" class="tcp-select !w-auto !py-1.5 text-xs">
|
|
903
|
+
<option value="">All kinds</option>
|
|
904
|
+
<option value="task_transition">task_transition</option>
|
|
905
|
+
<option value="task_reason">task_reason</option>
|
|
906
|
+
</select>
|
|
907
|
+
<input id="swarm-reason-task" class="tcp-input !w-44 !py-1.5 text-xs" placeholder="Filter by task id" />
|
|
908
|
+
</div>
|
|
909
|
+
</div>
|
|
910
|
+
<div id="swarm-reasons" class="grid max-h-[420px] gap-2 overflow-auto"></div>
|
|
911
|
+
</div>
|
|
912
|
+
|
|
913
|
+
<div class="grid gap-4 lg:grid-cols-2">
|
|
914
|
+
<div class="tcp-card">
|
|
915
|
+
<h3 class="tcp-title mb-3">Tasks (${p.length})</h3>
|
|
916
|
+
<div id="swarm-tasks" class="grid max-h-[420px] gap-2 overflow-auto"></div>
|
|
917
|
+
</div>
|
|
918
|
+
<div class="tcp-card">
|
|
919
|
+
<h3 class="tcp-title mb-3">Swarm Logs</h3>
|
|
920
|
+
<pre id="swarm-logs" class="tcp-code max-h-[420px] overflow-auto"></pre>
|
|
921
|
+
</div>
|
|
922
|
+
</div>
|
|
923
|
+
`;const w=n("swarm-tasks");w.innerHTML=p.sort(($,O)=>(O.lastUpdateMs||0)-($.lastUpdateMs||0)).map($=>`<div class="tcp-list-item"><div class="flex items-center justify-between gap-2"><strong>${s($.taskId)}</strong><span class="${lr($.status)}">${s($.status||"unknown")}</span></div><div class="mt-1 text-xs uppercase tracking-wide text-slate-400">${s($.ownerRole||"")}</div><div class="tcp-subtle mt-1">${s($.statusReason||"")}</div></div>`).join("")||'<p class="tcp-subtle">No swarm tasks yet.</p>';function h(){const $=n("swarm-reason-kind").value.trim(),O=n("swarm-reason-task").value.trim().toLowerCase(),V=f.filter(T=>!($&&T.kind!==$||O&&!String(T.taskId||"").toLowerCase().includes(O)));n("swarm-reasons").innerHTML=V.map(T=>`
|
|
924
|
+
<div class="tcp-list-item">
|
|
925
|
+
<div class="flex items-center justify-between gap-2"><span class="text-xs text-slate-400">${new Date(T.at).toLocaleTimeString()}</span><span class="${lr(T.to||T.from)}">${s(T.kind||"reason")}</span></div>
|
|
926
|
+
<div class="mt-1"><strong>${s(T.taskId||"swarm")}</strong> <span class="tcp-subtle">${s(T.role||"")}</span></div>
|
|
927
|
+
<div class="mt-1 text-sm text-slate-300">${s(Gg(T))}</div>
|
|
928
|
+
</div>
|
|
929
|
+
`).join("")||'<p class="tcp-subtle">No timeline reasons yet.</p>'}n("swarm-reason-kind").addEventListener("change",h),n("swarm-reason-task").addEventListener("input",h),h(),n("swarm-logs").textContent=(d.logs||[]).slice(-200).map($=>`[${new Date($.at).toLocaleTimeString()}] ${$.stream}: ${$.line}`).join(`
|
|
930
|
+
`),n("swarm-start").addEventListener("click",async()=>{try{await t("/api/swarm/start",{method:"POST",body:JSON.stringify({workspaceRoot:n("swarm-root").value.trim(),objective:n("swarm-objective").value.trim(),maxTasks:Number.parseInt(n("swarm-max").value,10)||3})}),r("ok","Swarm started."),jn(e)}catch($){r("err",$ instanceof Error?$.message:String($))}}),n("swarm-stop").addEventListener("click",async()=>{try{await t("/api/swarm/stop",{method:"POST"}),r("ok","Swarm stop requested."),jn(e)}catch($){r("err",$ instanceof Error?$.message:String($))}});const _=setInterval(()=>{i.route==="swarm"&&jn(e)},4e3),A=()=>clearInterval(_);i.__swarmLiveCleanup.push(A),o(A);try{const $=new EventSource("/api/swarm/events",{withCredentials:!0});$.onmessage=()=>{i.route==="swarm"&&jn(e)},$.onerror=()=>$.close();const O=()=>$.close();i.__swarmLiveCleanup.push(O),o(O)}catch{}}function Xg(e){const t=Number(e||0);return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function Yg(e){const t=Number(e||0);return t?new Date(t).toLocaleString():"n/a"}const Qg={md:"text/markdown",txt:"text/plain",csv:"text/csv",json:"application/json",pdf:"application/pdf",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp"};function nc(e=""){const t=String(e).toLowerCase().split(".").pop()||"";return Qg[t]||"application/octet-stream"}function ev(e,t){if(!e||!t)return t||"";const n=String(e).replace(/[\\/]+$/,""),s=String(t).replace(/^[\\/]+/,"");return`${n}/${s}`}function uo(e){const t=String(e?.root||"").trim();return(Array.isArray(e)?e:Array.isArray(e?.files)?e.files:Array.isArray(e?.entries)?e.entries:Array.isArray(e?.items)?e.items:[]).map(s=>{if(typeof s=="string"){const o=s.replace(/^\/+/,"");return{name:o.split("/").pop()||o,path:o,size:0,updatedAt:0}}const r=String(s.relative_to_base||s.path||s.key||s.name||"").replace(/^\/+/,"");if(!r)return null;const i=String(s.name||r.split("/").pop()||r);return{name:i,path:r,size:Number(s.size||s.size_bytes||s.bytes||0),updatedAt:Number(s.updatedAt||s.modified_at_ms||s.modifiedAt||s.mtimeMs||0),mime:nc(i),url:String(s.absPath||s.absolute_path||ev(t,r)||r)}}).filter(Boolean)}function sc(e){return String(e||"").trim().replace(/\\/g,"/").replace(/^\/+/,"").replace(/\/+$/,"")}const ws="control-panel",po="channel_uploads";function tv(e){const t=sc(e);return t===ws||t.startsWith(`${ws}/`)?t:ws}async function nv(e){const{state:t,byId:n,api:s,escapeHtml:r,toast:i,renderIcons:o,setRoute:c}=e,l=new Map,d=[],p=tv(t.filesDir||ws);t.filesDir=p,n("view").innerHTML=`
|
|
931
|
+
<div class="tcp-card grid gap-3">
|
|
932
|
+
<div class="flex flex-wrap items-center justify-between gap-2">
|
|
933
|
+
<h3 class="tcp-title">Storage Browser</h3>
|
|
934
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
935
|
+
<label for="files-upload-input" class="tcp-btn cursor-pointer"><i data-lucide="file-up"></i> Upload Files</label>
|
|
936
|
+
<input id="files-upload-input" type="file" class="hidden" multiple />
|
|
937
|
+
<button id="files-refresh" class="tcp-btn"><i data-lucide="refresh-cw"></i> Refresh</button>
|
|
938
|
+
</div>
|
|
939
|
+
</div>
|
|
940
|
+
<div id="files-upload-progress" class="grid gap-1.5"></div>
|
|
941
|
+
<div class="overflow-auto rounded-xl border border-slate-700 bg-black/20">
|
|
942
|
+
<table class="w-full min-w-[760px] text-sm">
|
|
943
|
+
<thead class="border-b border-slate-700 bg-slate-900/40 text-left text-slate-400">
|
|
944
|
+
<tr>
|
|
945
|
+
<th class="px-3 py-2">Name</th>
|
|
946
|
+
<th class="px-3 py-2">Path</th>
|
|
947
|
+
<th class="px-3 py-2">Size</th>
|
|
948
|
+
<th class="px-3 py-2">Updated</th>
|
|
949
|
+
<th class="px-3 py-2 text-right">Actions</th>
|
|
950
|
+
</tr>
|
|
951
|
+
</thead>
|
|
952
|
+
<tbody id="files-table"></tbody>
|
|
953
|
+
</table>
|
|
954
|
+
</div>
|
|
955
|
+
</div>
|
|
956
|
+
`;const f=n("files-table"),b=n("files-upload-progress"),w=n("files-upload-input");function h(){const S=[...l.entries()];b.innerHTML=S.map(([M,C])=>{const I=Math.max(0,Math.min(100,Number(C.progress||0)));return`
|
|
957
|
+
<div class="rounded-lg border border-slate-700/70 bg-slate-900/40 px-2 py-1.5">
|
|
958
|
+
<div class="mb-1 flex items-center justify-between gap-2 text-xs">
|
|
959
|
+
<span class="truncate text-slate-200">${r(C.name)}</span>
|
|
960
|
+
<span class="${C.error?"text-rose-300":"text-slate-400"}">${C.error?r(C.error):`${I}%`}</span>
|
|
961
|
+
</div>
|
|
962
|
+
<div class="h-1.5 overflow-hidden rounded-full bg-slate-800">
|
|
963
|
+
<div class="h-full rounded-full bg-slate-400/80 transition-all duration-150" style="width:${I}%"></div>
|
|
964
|
+
</div>
|
|
965
|
+
</div>
|
|
966
|
+
`}).join("")}function _(){if(!d.length){f.innerHTML='<tr><td colspan="5" class="px-3 py-5 text-center text-slate-400">No files in this directory.</td></tr>';return}f.innerHTML=d.map((S,M)=>`
|
|
967
|
+
<tr class="border-b border-slate-800/70">
|
|
968
|
+
<td class="px-3 py-2 font-medium text-slate-200">
|
|
969
|
+
${r(S.name)}
|
|
970
|
+
</td>
|
|
971
|
+
<td class="px-3 py-2 font-mono text-xs text-slate-400">${r(S.path)}</td>
|
|
972
|
+
<td class="px-3 py-2 text-slate-300">${r(Xg(S.size))}</td>
|
|
973
|
+
<td class="px-3 py-2 text-slate-400">${r(Yg(S.updatedAt))}</td>
|
|
974
|
+
<td class="px-3 py-2">
|
|
975
|
+
<div class="flex justify-end gap-1.5">
|
|
976
|
+
<button type="button" class="tcp-btn px-2.5" data-use-chat="${M}" title="Use in chat">Use in Chat</button>
|
|
977
|
+
<a class="tcp-btn px-2.5" href="/api/files/download?path=${encodeURIComponent(S.path)}" title="Download"><i data-lucide="download"></i></a>
|
|
978
|
+
<button type="button" class="tcp-btn-danger px-2.5" data-del-file="${M}" title="Delete"><i data-lucide="trash-2"></i></button>
|
|
979
|
+
</div>
|
|
980
|
+
</td>
|
|
981
|
+
</tr>
|
|
982
|
+
`).join(""),f.querySelectorAll("[data-use-chat]").forEach(S=>{S.addEventListener("click",()=>{const M=Number(S.dataset.useChat);if(!Number.isFinite(M)||!d[M])return;const C=d[M];(t.chatUploadedFiles||[]).some(L=>L.path===C.path)||(t.chatUploadedFiles=[{name:C.name,path:C.path,size:C.size,mime:C.mime||nc(C.name),url:C.url||C.path,attach:!0},...t.chatUploadedFiles||[]]),i("ok",`${C.name} added to chat attachments.`),c("chat")})}),f.querySelectorAll("[data-del-file]").forEach(S=>{S.addEventListener("click",async()=>{const M=Number(S.dataset.delFile);if(!Number.isFinite(M)||!d[M])return;const C=d[M];if(window.confirm(`Delete ${C.path}?`))try{await s("/api/files/delete",{method:"POST",body:JSON.stringify({path:C.path})}),i("ok",`${C.name} deleted.`),await O()}catch(I){i("err",I instanceof Error?I.message:String(I))}})}),o(f)}async function A(S){const M=S?`${po}/${S}`:po,C=`?path=${encodeURIComponent(M)}`,I=await s(`/api/engine/global/storage/files${C}`);return uo(I)}async function $(S){const M=S?`?dir=${encodeURIComponent(S)}`:"",C=await s(`/api/files/list${M}`);return uo(C)}async function O(){try{let S=[];try{S=await A(p)}catch{S=await $(p)}const M=S.map(C=>{const I=sc(C.path||"");if(!I)return null;const L=I.split("/").pop()||I;return{...C,kind:"file",name:L,path:I}}).filter(Boolean).sort((C,I)=>C.path.localeCompare(I.path));d.splice(0,d.length,...M),_()}catch(S){i("err",S instanceof Error?S.message:String(S))}}function V(S){return new Promise((M,C)=>{const I=`${Date.now()}-${Math.random().toString(16).slice(2)}`;l.set(I,{name:S.name,progress:0,error:""}),h();const L=new XMLHttpRequest,P=p?`?dir=${encodeURIComponent(p)}`:"";L.open("POST",`/api/files/upload${P}`),L.withCredentials=!0,L.responseType="json",L.setRequestHeader("x-file-name",encodeURIComponent(S.name)),L.upload.onprogress=K=>{if(!K.lengthComputable)return;const se=l.get(I);se&&(se.progress=K.loaded/K.total*100,h())},L.onerror=()=>{const K=l.get(I);K&&(K.error="Network error"),h(),setTimeout(()=>{l.delete(I),h()},1200),C(new Error(`Upload failed: ${S.name}`))},L.onload=()=>{const K=L.response||{};if(L.status<200||L.status>=300||K?.ok===!1){const se=K?.error||`Upload failed (${L.status})`,G=l.get(I);G&&(G.error=String(se)),h(),setTimeout(()=>{l.delete(I),h()},1800),C(new Error(String(se)));return}l.delete(I),h(),M(K)},L.send(S)})}async function T(S){const M=[...S||[]];if(!M.length)return;let C=0;for(const I of M)try{await V(I),C+=1}catch(L){i("err",L instanceof Error?L.message:String(L))}C>0&&(i("ok",`Uploaded ${C} file${C===1?"":"s"} to tandem/${p||"."}.`),await O())}n("files-refresh").addEventListener("click",()=>{O()}),w.addEventListener("change",async()=>{await T(w.files),w.value=""}),o(n("view")),await O()}async function Er(e){const{state:t,byId:n,toast:s,escapeHtml:r}=e,o=(await t.client.memory.list({limit:100}).catch(()=>({items:[]}))).items||[];n("view").innerHTML=`
|
|
983
|
+
<div class="tcp-card">
|
|
984
|
+
<div class="mb-3 flex items-center justify-between">
|
|
985
|
+
<h3 class="tcp-title">Memory</h3>
|
|
986
|
+
<span class="tcp-badge-info">${o.length} records</span>
|
|
987
|
+
</div>
|
|
988
|
+
<div class="grid gap-3 md:grid-cols-[1fr_auto_auto]">
|
|
989
|
+
<input id="mem-query" class="tcp-input" placeholder="Search query" />
|
|
990
|
+
<button id="mem-search" class="tcp-btn-primary"><i data-lucide="search"></i> Search</button>
|
|
991
|
+
<button id="mem-refresh" class="tcp-btn"><i data-lucide="refresh-cw"></i></button>
|
|
992
|
+
</div>
|
|
993
|
+
<div id="mem-results" class="tcp-list mt-3"></div>
|
|
994
|
+
</div>
|
|
995
|
+
`;const c=l=>{n("mem-results").innerHTML=l.map(d=>`
|
|
996
|
+
<div class="tcp-list-item flex items-center justify-between gap-3">
|
|
997
|
+
<div>
|
|
998
|
+
<strong class="font-mono text-xs text-slate-300">${r(d.id||"(no id)")}</strong>
|
|
999
|
+
<div class="tcp-subtle mt-1">${r((d.text||d.content||"").slice(0,140))}</div>
|
|
1000
|
+
</div>
|
|
1001
|
+
<button data-del="${r(d.id||"")}" class="tcp-btn-danger"><i data-lucide="trash-2"></i></button>
|
|
1002
|
+
</div>
|
|
1003
|
+
`).join("")||'<p class="tcp-subtle">No memory records.</p>',n("mem-results").querySelectorAll("[data-del]").forEach(d=>d.addEventListener("click",async()=>{const p=d.dataset.del;if(p)try{await t.client.memory.delete(p),s("ok","Memory deleted."),Er(e)}catch(f){s("err",f instanceof Error?f.message:String(f))}}))};c(o),n("mem-refresh").addEventListener("click",()=>Er(e)),n("mem-search").addEventListener("click",async()=>{const l=n("mem-query").value.trim();if(!l)return c(o);try{const d=await t.client.memory.search({query:l,limit:50});c(d.results||[])}catch(d){s("err",d instanceof Error?d.message:String(d))}})}function vs(e){return Array.isArray(e)?e:[]}function sv(e){return e?.id||e?.instanceID||e?.missionID||e?.templateID||"(unknown)"}function rv(e){return e?.status||e?.state||e?.phase||"unknown"}function dr(e,t){return t?JSON.stringify(e||{}).toLowerCase().includes(t):!0}function ur(e,t,n,s="id"){return e.length?e.map(r=>{const i=n(r?.[s]||sv(r)),o=n(rv(r));return`
|
|
1004
|
+
<article class="tcp-list-item">
|
|
1005
|
+
<div class="flex items-center justify-between gap-2">
|
|
1006
|
+
<strong>${i}</strong>
|
|
1007
|
+
<span class="tcp-badge-info">${o}</span>
|
|
1008
|
+
</div>
|
|
1009
|
+
<div class="tcp-subtle mt-1">role: ${n(r?.role||r?.ownerRole||"n/a")}</div>
|
|
1010
|
+
<div class="tcp-subtle">mission: ${n(r?.missionID||r?.missionId||r?.mission||"n/a")}</div>
|
|
1011
|
+
<details class="mt-2">
|
|
1012
|
+
<summary class="cursor-pointer text-xs text-slate-400">Details</summary>
|
|
1013
|
+
<pre class="tcp-code mt-2">${n(JSON.stringify(r,null,2))}</pre>
|
|
1014
|
+
</details>
|
|
1015
|
+
</article>
|
|
1016
|
+
`}).join(""):`<p class="tcp-subtle">${t}</p>`}async function _s(e){const{state:t,byId:n,toast:s,escapeHtml:r}=e,[i,o,c,l]=await Promise.all([t.client.agentTeams.listTemplates().catch(()=>({templates:[]})),t.client.agentTeams.listInstances().catch(()=>({instances:[]})),t.client.agentTeams.listMissions().catch(()=>({missions:[]})),t.client.agentTeams.listApprovals().catch(()=>({spawnApprovals:[]}))]),d=vs(i.templates),p=vs(o.instances),f=vs(c.missions),b=vs(l.spawnApprovals);n("view").innerHTML=`
|
|
1017
|
+
<div class="tcp-card">
|
|
1018
|
+
<h3 class="tcp-title mb-3">Spawn Agent Team Instance</h3>
|
|
1019
|
+
<div class="grid gap-3 md:grid-cols-4">
|
|
1020
|
+
<input id="team-mission" class="tcp-input" placeholder="missionID" />
|
|
1021
|
+
<input id="team-role" class="tcp-input" placeholder="role" value="worker" />
|
|
1022
|
+
<input id="team-template" class="tcp-input" placeholder="templateID" value="worker-default" />
|
|
1023
|
+
<button id="team-spawn" class="tcp-btn-primary">Spawn</button>
|
|
1024
|
+
</div>
|
|
1025
|
+
</div>
|
|
1026
|
+
|
|
1027
|
+
<div class="tcp-card">
|
|
1028
|
+
<div class="mb-3 flex items-center justify-between gap-3">
|
|
1029
|
+
<h3 class="tcp-title">Teams & Missions</h3>
|
|
1030
|
+
<input id="teams-filter" class="tcp-input max-w-sm" placeholder="Filter instances/missions/templates" />
|
|
1031
|
+
</div>
|
|
1032
|
+
|
|
1033
|
+
<div class="grid gap-4 lg:grid-cols-2">
|
|
1034
|
+
<section>
|
|
1035
|
+
<h4 class="mb-2 font-medium">Approvals (${b.length})</h4>
|
|
1036
|
+
<div id="team-approvals" class="tcp-list"></div>
|
|
1037
|
+
</section>
|
|
1038
|
+
<section>
|
|
1039
|
+
<h4 class="mb-2 font-medium">Instances (${p.length})</h4>
|
|
1040
|
+
<div id="team-instances" class="tcp-list"></div>
|
|
1041
|
+
</section>
|
|
1042
|
+
</div>
|
|
1043
|
+
|
|
1044
|
+
<div class="mt-4 grid gap-4 lg:grid-cols-2">
|
|
1045
|
+
<section>
|
|
1046
|
+
<h4 class="mb-2 font-medium">Missions (${f.length})</h4>
|
|
1047
|
+
<div id="team-missions" class="tcp-list"></div>
|
|
1048
|
+
</section>
|
|
1049
|
+
<section>
|
|
1050
|
+
<h4 class="mb-2 font-medium">Templates (${d.length})</h4>
|
|
1051
|
+
<div id="team-templates" class="tcp-list"></div>
|
|
1052
|
+
</section>
|
|
1053
|
+
</div>
|
|
1054
|
+
</div>
|
|
1055
|
+
`,n("team-spawn").addEventListener("click",async()=>{try{await t.client.agentTeams.spawn({missionID:n("team-mission").value.trim(),role:n("team-role").value.trim()||"worker",templateID:n("team-template").value.trim()||"worker-default",source:"ui_action",justification:"spawn from control panel"}),s("ok","Spawn requested."),_s(e)}catch(_){s("err",_ instanceof Error?_.message:String(_))}});function w(){const _=n("teams-filter").value.trim().toLowerCase(),A=p.filter(V=>dr(V,_)),$=f.filter(V=>dr(V,_)),O=d.filter(V=>dr(V,_));n("team-instances").innerHTML=ur(A,"No instances.",r,"instanceID"),n("team-missions").innerHTML=ur($,"No missions.",r,"missionID"),n("team-templates").innerHTML=ur(O,"No templates.",r,"templateID")}const h=n("team-approvals");h.innerHTML=b.map(_=>{const A=r(_.approvalID||_.id||"");return`
|
|
1056
|
+
<div class="tcp-list-item flex items-center justify-between gap-3">
|
|
1057
|
+
<div>
|
|
1058
|
+
<div><strong>${A||"approval"}</strong></div>
|
|
1059
|
+
<div class="tcp-subtle">mission: ${r(_.missionID||_.missionId||"n/a")}</div>
|
|
1060
|
+
</div>
|
|
1061
|
+
<div class="flex gap-2">
|
|
1062
|
+
<button data-ap="${A}" class="tcp-btn-primary">Approve</button>
|
|
1063
|
+
<button data-den="${A}" class="tcp-btn-danger">Deny</button>
|
|
1064
|
+
</div>
|
|
1065
|
+
</div>`}).join("")||'<p class="tcp-subtle">No pending spawn approvals.</p>',h.querySelectorAll("[data-ap]").forEach(_=>_.addEventListener("click",async()=>{try{await t.client.agentTeams.approveSpawn(_.dataset.ap,"approved in portal"),s("ok","Approved."),_s(e)}catch(A){s("err",A instanceof Error?A.message:String(A))}})),h.querySelectorAll("[data-den]").forEach(_=>_.addEventListener("click",async()=>{try{await t.client.agentTeams.denySpawn(_.dataset.den,"denied in portal"),s("ok","Denied."),_s(e)}catch(A){s("err",A instanceof Error?A.message:String(A))}})),n("teams-filter").addEventListener("input",w),w()}function mo(e){return e?.type||e?.event||"event"}function iv(e){const t=String(e||"").toLowerCase();return t.includes("fail")||t.includes("error")?"tcp-badge-err":t.includes("warn")||t.includes("retry")?"tcp-badge-warn":"tcp-badge-info"}async function ov(e){const{byId:t,escapeHtml:n,state:s,addCleanup:r,toast:i}=e;t("view").innerHTML=`
|
|
1066
|
+
<div class="tcp-card">
|
|
1067
|
+
<div class="mb-3 flex flex-wrap items-center justify-between gap-3">
|
|
1068
|
+
<h3 class="tcp-title flex items-center gap-2"><i data-lucide="activity"></i> Global Live Feed</h3>
|
|
1069
|
+
<div class="flex gap-2">
|
|
1070
|
+
<input id="feed-filter" class="tcp-input min-w-[220px]" placeholder="Filter by type or payload" />
|
|
1071
|
+
<button id="feed-clear" class="tcp-btn">Clear</button>
|
|
1072
|
+
</div>
|
|
1073
|
+
</div>
|
|
1074
|
+
<div id="feed-events" class="grid max-h-[68vh] gap-2 overflow-auto rounded-xl border border-slate-700 bg-black/20 p-2"></div>
|
|
1075
|
+
</div>
|
|
1076
|
+
`;const o=t("feed-events"),c=[];function l(){const p=t("feed-filter").value.trim().toLowerCase(),f=c.filter(b=>p?`${mo(b.data)} ${JSON.stringify(b.data||{})}`.toLowerCase().includes(p):!0);o.innerHTML=f.map(b=>{const w=mo(b.data);return`
|
|
1077
|
+
<article class="tcp-list-item">
|
|
1078
|
+
<div class="flex items-center justify-between gap-2">
|
|
1079
|
+
<strong>${n(w)}</strong>
|
|
1080
|
+
<span class="${iv(w)}">${new Date(b.at).toLocaleTimeString()}</span>
|
|
1081
|
+
</div>
|
|
1082
|
+
<div class="tcp-subtle mt-1">session: ${n(b.data?.sessionID||b.data?.sessionId||"n/a")} run: ${n(b.data?.runID||b.data?.runId||"n/a")}</div>
|
|
1083
|
+
<details class="mt-2">
|
|
1084
|
+
<summary class="cursor-pointer text-xs text-slate-400">Payload</summary>
|
|
1085
|
+
<pre class="tcp-code mt-2">${n(JSON.stringify(b.data,null,2))}</pre>
|
|
1086
|
+
</details>
|
|
1087
|
+
</article>
|
|
1088
|
+
`}).join("")||'<p class="tcp-subtle">No events yet.</p>',o.scrollTop=o.scrollHeight}const d=new EventSource("/api/engine/global/event",{withCredentials:!0});d.onmessage=p=>{try{const f=JSON.parse(p.data);for(c.push({at:Date.now(),data:f});c.length>300;)c.shift();s.route==="feed"&&l()}catch{}},d.onerror=()=>{d.close(),i("err","Live feed disconnected.")},t("feed-filter").addEventListener("input",l),t("feed-clear").addEventListener("click",()=>{c.length=0,l()}),r(()=>d.close()),l()}const Et="__custom_provider__";async function rc(e){const{byId:t,state:n,escapeHtml:s}=e;t("view").innerHTML=`
|
|
1089
|
+
<div class="tcp-card">
|
|
1090
|
+
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
|
1091
|
+
<h3 class="tcp-title flex items-center gap-2"><i data-lucide="settings-2"></i> Provider Setup Wizard</h3>
|
|
1092
|
+
<span class="${n.providerReady?"tcp-badge-ok":"tcp-badge-warn"}">${n.providerReady?"Ready":"Not Configured"}</span>
|
|
1093
|
+
</div>
|
|
1094
|
+
<p class="tcp-subtle">Step 1: Select provider. Step 2: Configure model. Step 3: Add key (if required). Step 4: Run test. Step 5: Set bot identity + personality.</p>
|
|
1095
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
1096
|
+
<span class="${n.providerDefault?"tcp-badge-ok":"tcp-badge-warn"}">Default: ${s(n.providerDefault||"none")}</span>
|
|
1097
|
+
<span class="${n.providerConnected.length>0?"tcp-badge-info":"tcp-badge-warn"}">Connected: ${n.providerConnected.length}</span>
|
|
1098
|
+
</div>
|
|
1099
|
+
${n.providerError?`<p class="mt-3 rounded-xl border border-amber-700/60 bg-amber-950/30 px-3 py-2 text-sm text-amber-300"><i data-lucide="triangle-alert"></i> ${s(n.providerError)}</p>`:""}
|
|
1100
|
+
<div id="provider-settings" class="mt-4"></div>
|
|
1101
|
+
<div id="identity-settings" class="mt-6 border-t border-slate-800 pt-5"></div>
|
|
1102
|
+
</div>
|
|
1103
|
+
<div class="tcp-card">
|
|
1104
|
+
<h3 class="tcp-title mb-2 flex items-center gap-2"><i data-lucide="shield"></i> Session Authorization</h3>
|
|
1105
|
+
<p class="tcp-subtle">Use Logout in the sidebar to clear your current portal session token binding.</p>
|
|
1106
|
+
</div>
|
|
1107
|
+
`,await av(e,t("provider-settings")),await cv(e,t("identity-settings"))}async function av(e,t){const{state:n,api:s,toast:r,escapeHtml:i,providerHints:o,refreshProviderStatus:c}=e,l=await n.client.providers.catalog(),d=await n.client.providers.config(),p=l.all||[],f=new Set(p.map(S=>S.id)),b=String(l.default||d.default||p[0]?.id||"").trim();let w=f.has(b)?b:Et,h="",_=w===Et?b:"",A=_?String(d.providers?.[_]?.url||""):"",$=_?String(d.providers?.[_]?.defaultModel||d.providers?.[_]?.default_model||""):"";const O=()=>{if(w===Et)return;const S=p.find(I=>I.id===w),M=Object.keys(S?.models||{}),C=d.providers?.[w]||{};h=C.defaultModel||C.default_model||M[0]||""};O();const V=[...p.map(S=>({id:S.id,label:o[S.id]?.label||S.name||S.id})),{id:Et,label:"Custom Provider"}],T=()=>{const S=w===Et?[]:Object.keys((p.find(P=>P.id===w)||{}).models||{});t.innerHTML=`
|
|
1108
|
+
<div class="grid gap-3 md:grid-cols-2">
|
|
1109
|
+
<div>
|
|
1110
|
+
<label class="mb-1 block text-sm text-slate-300">Provider</label>
|
|
1111
|
+
<select id="provider-select" class="tcp-select">
|
|
1112
|
+
${V.map(P=>`<option value="${i(P.id)}" ${P.id===w?"selected":""}>${i(P.label)}</option>`).join("")}
|
|
1113
|
+
</select>
|
|
1114
|
+
</div>
|
|
1115
|
+
${w===Et?`<div>
|
|
1116
|
+
<label class="mb-1 block text-sm text-slate-300">Custom Provider ID</label>
|
|
1117
|
+
<input id="custom-provider-id" class="tcp-input" placeholder="my-provider" value="${i(_)}" />
|
|
1118
|
+
</div>`:`<div>
|
|
1119
|
+
<label class="mb-1 block text-sm text-slate-300">Model</label>
|
|
1120
|
+
<select id="provider-model" class="tcp-select">${S.map(P=>`<option ${P===h?"selected":""}>${i(P)}</option>`).join("")}</select>
|
|
1121
|
+
</div>`}
|
|
1122
|
+
</div>
|
|
1123
|
+
|
|
1124
|
+
${w===Et?`<div class="mt-3 grid gap-3 md:grid-cols-2">
|
|
1125
|
+
<div>
|
|
1126
|
+
<label class="mb-1 block text-sm text-slate-300">Base URL</label>
|
|
1127
|
+
<input id="custom-provider-url" class="tcp-input" placeholder="https://api.example.com/v1" value="${i(A)}" />
|
|
1128
|
+
</div>
|
|
1129
|
+
<div>
|
|
1130
|
+
<label class="mb-1 block text-sm text-slate-300">Default Model</label>
|
|
1131
|
+
<input id="custom-provider-model" class="tcp-input" placeholder="gpt-4o-mini" value="${i($)}" />
|
|
1132
|
+
</div>
|
|
1133
|
+
</div>
|
|
1134
|
+
<p class="tcp-subtle mt-2">Custom providers use OpenAI-compatible chat completions endpoints.</p>`:""}
|
|
1135
|
+
|
|
1136
|
+
<div class="mt-3 grid gap-3 md:grid-cols-2">
|
|
1137
|
+
<div>
|
|
1138
|
+
<label class="mb-1 block text-sm text-slate-300">API Key (optional)</label>
|
|
1139
|
+
<input id="provider-key" class="tcp-input" type="password" placeholder="${i(o[w]?.placeholder||"sk-...")}" />
|
|
1140
|
+
</div>
|
|
1141
|
+
<div class="flex items-end justify-end gap-2">
|
|
1142
|
+
<button id="provider-test" class="tcp-btn"><i data-lucide="flask-conical"></i> Test Model Run</button>
|
|
1143
|
+
<button id="provider-save" class="tcp-btn-primary"><i data-lucide="save"></i> Save Provider</button>
|
|
1144
|
+
</div>
|
|
1145
|
+
</div>
|
|
1146
|
+
`,t.querySelector("#provider-select").addEventListener("change",P=>{w=P.target.value,w!==Et&&O(),T()});const M=t.querySelector("#provider-model");M&&M.addEventListener("change",P=>h=P.target.value);const C=t.querySelector("#custom-provider-id");C&&C.addEventListener("input",P=>_=P.target.value.trim());const I=t.querySelector("#custom-provider-url");I&&I.addEventListener("input",P=>A=P.target.value.trim());const L=t.querySelector("#custom-provider-model");L&&L.addEventListener("input",P=>$=P.target.value.trim()),t.querySelector("#provider-save").addEventListener("click",async()=>{const P=t.querySelector("#provider-key").value.trim();try{if(w===Et){if(!_)throw new Error("Custom provider ID is required.");if(!A)throw new Error("Custom provider URL is required.");if(!$)throw new Error("Custom default model is required.");await s("/api/engine/config",{method:"PATCH",body:JSON.stringify({default_provider:_,providers:{[_]:{url:A,default_model:$}}})}),P&&await n.client.providers.setApiKey(_,P)}else P&&await n.client.providers.setApiKey(w,P),await n.client.providers.setDefaults(w,h);await c(),r("ok","Provider configuration saved."),rc(e)}catch(K){r("err",K instanceof Error?K.message:String(K))}}),t.querySelector("#provider-test").addEventListener("click",async()=>{try{const P=await n.client.sessions.create({title:`Provider test ${new Date().toISOString()}`}),{runId:K}=await n.client.sessions.promptAsync(P,"Reply with exactly: READY");let se=!1;for await(const G of n.client.stream(P,K))if(G.type==="session.response"&&String(G.properties?.delta||"").trim()&&(se=!0),G.type==="run.complete"||G.type==="run.failed"||G.type==="session.run.finished")break;if(!se)throw new Error("No model tokens received. Save provider + key first, then retry.");await c(),r("ok","Model run test succeeded.")}catch(P){r("err",P instanceof Error?P.message:String(P))}})};T()}async function cv(e,t){const{state:n,toast:s,escapeHtml:r,refreshIdentityStatus:i,renderShell:o,renderIcons:c,api:l}=e,d=async()=>n.client?.identity?.get?n.client.identity.get():l("/api/engine/config/identity",{method:"GET"}),p=async I=>n.client?.identity?.patch?n.client.identity.patch(I):l("/api/engine/config/identity",{method:"PATCH",body:JSON.stringify(I)});let f;try{f=await d()}catch(I){t.innerHTML=`
|
|
1147
|
+
<p class="rounded-xl border border-rose-700/60 bg-rose-950/30 px-3 py-2 text-sm text-rose-300">
|
|
1148
|
+
Failed to load identity settings: ${r(I instanceof Error?I.message:String(I))}
|
|
1149
|
+
</p>
|
|
1150
|
+
`;return}const b=f?.identity||{},w=b?.bot||{},h=w?.aliases||{},A=(b?.personality||{})?.default||{},$=Array.isArray(f?.presets)&&f.presets.length>0?f.presets:[{id:"balanced",label:"Balanced"},{id:"concise",label:"Concise"},{id:"friendly",label:"Friendly"},{id:"mentor",label:"Mentor"},{id:"critical",label:"Critical"}];let O=String(w?.canonical_name||w?.canonicalName||"").trim(),V=String(w?.avatar_url||w?.avatarUrl||"").trim(),T=String(h?.control_panel||h?.controlPanel||"").trim(),S=String(A?.preset||"balanced").trim()||"balanced",M=String(A?.custom_instructions||A?.customInstructions||"").trim();const C=()=>{t.innerHTML=`
|
|
1151
|
+
<div class="mb-3">
|
|
1152
|
+
<h4 class="tcp-title flex items-center gap-2"><i data-lucide="bot"></i> Identity & Personality</h4>
|
|
1153
|
+
<p class="tcp-subtle mt-1">Control assistant naming and default response style.</p>
|
|
1154
|
+
</div>
|
|
1155
|
+
|
|
1156
|
+
<div class="grid gap-3 md:grid-cols-2">
|
|
1157
|
+
<div>
|
|
1158
|
+
<label class="mb-1 block text-sm text-slate-300">Canonical bot name</label>
|
|
1159
|
+
<input id="identity-canonical-name" class="tcp-input" placeholder="Assistant" value="${r(O)}" />
|
|
1160
|
+
</div>
|
|
1161
|
+
<div>
|
|
1162
|
+
<label class="mb-1 block text-sm text-slate-300">Control panel alias (optional)</label>
|
|
1163
|
+
<input id="identity-control-panel-alias" class="tcp-input" placeholder="Assistant Control Panel" value="${r(T)}" />
|
|
1164
|
+
</div>
|
|
1165
|
+
</div>
|
|
1166
|
+
|
|
1167
|
+
<div class="mt-3">
|
|
1168
|
+
<label class="mb-1 block text-sm text-slate-300">Avatar (optional)</label>
|
|
1169
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
1170
|
+
<div class="h-10 w-10 overflow-hidden rounded-xl border border-slate-600 bg-muted">
|
|
1171
|
+
<img src="${r(V||"/tandem-logo.png")}" alt="${r(O||"Assistant")}" class="h-full w-full object-cover" />
|
|
1172
|
+
</div>
|
|
1173
|
+
<input id="identity-avatar-file" type="file" accept="image/png,image/jpeg,image/webp,image/gif" class="tcp-input !h-auto !py-1.5 text-xs" />
|
|
1174
|
+
${V?'<button id="identity-avatar-clear" class="tcp-btn h-8 px-2 text-xs">Remove</button>':""}
|
|
1175
|
+
</div>
|
|
1176
|
+
</div>
|
|
1177
|
+
|
|
1178
|
+
<div class="mt-3 grid gap-3 md:grid-cols-2">
|
|
1179
|
+
<div>
|
|
1180
|
+
<label class="mb-1 block text-sm text-slate-300">Personality preset</label>
|
|
1181
|
+
<select id="identity-preset" class="tcp-select">
|
|
1182
|
+
${$.map(P=>`<option value="${r(P.id)}" ${P.id===S?"selected":""}>${r(P.label||P.id)}</option>`).join("")}
|
|
1183
|
+
</select>
|
|
1184
|
+
</div>
|
|
1185
|
+
</div>
|
|
1186
|
+
|
|
1187
|
+
<div class="mt-3">
|
|
1188
|
+
<label class="mb-1 block text-sm text-slate-300">Custom personality instructions (optional)</label>
|
|
1189
|
+
<textarea id="identity-custom-instructions" class="tcp-input min-h-[96px]" rows="4" placeholder="Keep responses concise and operationally focused.">${r(M)}</textarea>
|
|
1190
|
+
</div>
|
|
1191
|
+
|
|
1192
|
+
<div class="mt-3 flex items-center justify-end gap-2">
|
|
1193
|
+
<button id="identity-save" class="tcp-btn-primary"><i data-lucide="save"></i> Save Identity</button>
|
|
1194
|
+
</div>
|
|
1195
|
+
`,t.querySelector("#identity-canonical-name").addEventListener("input",P=>{O=P.target.value}),t.querySelector("#identity-control-panel-alias").addEventListener("input",P=>{T=P.target.value});const I=t.querySelector("#identity-avatar-file");I&&I.addEventListener("change",async P=>{const K=P.target?.files?.[0];if(!K)return;if(K.size>10*1024*1024){s("err","Avatar image is too large (max 10 MB).");return}const se=new FileReader;se.onload=()=>{const G=typeof se.result=="string"?se.result:"";if(!G){s("err","Failed to read avatar file.");return}V=G,C()},se.onerror=()=>s("err","Failed to read avatar file."),se.readAsDataURL(K)});const L=t.querySelector("#identity-avatar-clear");L&&L.addEventListener("click",()=>{V="",C()}),t.querySelector("#identity-preset").addEventListener("change",P=>{S=P.target.value}),t.querySelector("#identity-custom-instructions").addEventListener("input",P=>{M=P.target.value}),t.querySelector("#identity-save").addEventListener("click",async()=>{try{const P=O.trim();if(!P)throw new Error("Canonical bot name is required.");const K=T.trim(),se=M.trim(),G=await p({identity:{bot:{canonical_name:P,avatar_url:V||null,aliases:{control_panel:K||void 0}},personality:{default:{preset:S||"balanced",custom_instructions:se||null}}}});await i(),o(),s("ok","Identity settings saved."),f=G,O=String(G?.identity?.bot?.canonical_name||"").trim(),V=String(G?.identity?.bot?.avatar_url||"").trim(),T=String(G?.identity?.bot?.aliases?.control_panel||"").trim(),S=String(G?.identity?.personality?.default?.preset||"balanced").trim()||"balanced",M=String(G?.identity?.personality?.default?.custom_instructions||"").trim(),C()}catch(P){s("err",P instanceof Error?P.message:String(P))}}),c()};C()}const fo={dashboard:Dg,chat:Hg,agents:et,channels:Ar,mcp:Dn,swarm:jn,files:nv,memory:Er,teams:_s,feed:ov,settings:rc};const ic={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};const oc=([e,t,n])=>{const s=document.createElementNS("http://www.w3.org/2000/svg",e);return Object.keys(t).forEach(r=>{s.setAttribute(r,String(t[r]))}),n?.length&&n.forEach(r=>{const i=oc(r);s.appendChild(i)}),s},lv=(e,t={})=>{const s={...ic,...t};return oc(["svg",s,e])};const dv=e=>{for(const t in e)if(t.startsWith("aria-")||t==="role"||t==="title")return!0;return!1};const uv=(...e)=>e.filter((t,n,s)=>!!t&&t.trim()!==""&&s.indexOf(t)===n).join(" ").trim();const pv=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,n,s)=>s?s.toUpperCase():n.toLowerCase());const mv=e=>{const t=pv(e);return t.charAt(0).toUpperCase()+t.slice(1)};const fv=e=>Array.from(e.attributes).reduce((t,n)=>(t[n.name]=n.value,t),{}),ho=e=>typeof e=="string"?e:!e||!e.class?"":e.class&&typeof e.class=="string"?e.class.split(" "):e.class&&Array.isArray(e.class)?e.class:"",go=(e,{nameAttr:t,icons:n,attrs:s})=>{const r=e.getAttribute(t);if(r==null)return;const i=mv(r),o=n[i];if(!o)return console.warn(`${e.outerHTML} icon name was not found in the provided icons object.`);const c=fv(e),l=dv(c)?{}:{"aria-hidden":"true"},d={...ic,"data-lucide":r,...l,...s,...c},p=ho(c),f=ho(s),b=uv("lucide",`lucide-${r}`,...p,...f);b&&Object.assign(d,{class:b});const w=lv(o,d);return e.parentNode?.replaceChild(w,e)};const hv=[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"}]];const gv=[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]];const vv=[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M12 11h4"}],["path",{d:"M12 16h4"}],["path",{d:"M8 11h.01"}],["path",{d:"M8 16h.01"}]];const yv=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6h4"}]];const bv=[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 6v6l4 2"}]];const wv=[["path",{d:"M12 20v2"}],["path",{d:"M12 2v2"}],["path",{d:"M17 20v2"}],["path",{d:"M17 2v2"}],["path",{d:"M2 12h2"}],["path",{d:"M2 17h2"}],["path",{d:"M2 7h2"}],["path",{d:"M20 12h2"}],["path",{d:"M20 17h2"}],["path",{d:"M20 7h2"}],["path",{d:"M7 20v2"}],["path",{d:"M7 2v2"}],["rect",{x:"4",y:"4",width:"16",height:"16",rx:"2"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1"}]];const _v=[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5"}],["path",{d:"M3 12A9 3 0 0 0 21 12"}]];const Sv=[["path",{d:"M12 15V3"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}],["path",{d:"m7 10 5 5 5-5"}]];const xv=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5"}],["path",{d:"M12 12v6"}],["path",{d:"m15 15-3-3-3 3"}]];const $v=[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"}],["path",{d:"M6.453 15h11.094"}],["path",{d:"M8.5 2h7"}]];const kv=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"}]];const Tv=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}]];const Av=[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor"}]];const Ev=[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"}]];const Iv=[["path",{d:"m16 17 5-5-5-5"}],["path",{d:"M21 12H9"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}]];const Cv=[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"}]];const Rv=[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"}]];const Mv=[["path",{d:"M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"}],["path",{d:"M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"}]];const Pv=[["path",{d:"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551"}]];const zv=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"}]];const Ov=[["path",{d:"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z"}],["path",{d:"m2 22 3-3"}],["path",{d:"M7.5 13.5 10 11"}],["path",{d:"M10.5 16.5 13 14"}],["path",{d:"m18 3-4 4h6l-4 4"}]];const Nv=[["path",{d:"M5 12h14"}],["path",{d:"M12 5v14"}]];const Lv=[["path",{d:"M16.247 7.761a6 6 0 0 1 0 8.478"}],["path",{d:"M19.075 4.933a10 10 0 0 1 0 14.134"}],["path",{d:"M4.925 19.067a10 10 0 0 1 0-14.134"}],["path",{d:"M7.753 16.239a6 6 0 0 1 0-8.478"}],["circle",{cx:"12",cy:"12",r:"2"}]];const Dv=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}],["path",{d:"M8 16H3v5"}]];const jv=[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7"}]];const qv=[["path",{d:"m21 21-4.34-4.34"}],["circle",{cx:"11",cy:"11",r:"8"}]];const Vv=[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]];const Fv=[["path",{d:"M14 17H5"}],["path",{d:"M19 7h-9"}],["circle",{cx:"17",cy:"17",r:"3"}],["circle",{cx:"7",cy:"7",r:"3"}]];const Uv=[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"}],["circle",{cx:"12",cy:"12",r:"3"}]];const Zv=[["circle",{cx:"18",cy:"5",r:"3"}],["circle",{cx:"6",cy:"12",r:"3"}],["circle",{cx:"18",cy:"19",r:"3"}],["line",{x1:"8.59",x2:"15.42",y1:"13.51",y2:"17.49"}],["line",{x1:"15.41",x2:"8.59",y1:"6.51",y2:"10.49"}]];const Hv=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}]];const Bv=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]];const Jv=[["path",{d:"M10 11v6"}],["path",{d:"M14 11v6"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"}],["path",{d:"M3 6h18"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}]];const Kv=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"}],["path",{d:"M12 9v4"}],["path",{d:"M12 17h.01"}]];const Wv=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87"}],["circle",{cx:"9",cy:"7",r:"4"}]];const Gv=[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2"}]];const Xv=[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]];const ac=({icons:e={},nameAttr:t="data-lucide",attrs:n={},root:s=document,inTemplates:r}={})=>{if(!Object.values(e).length)throw new Error(`Please provide an icons object.
|
|
1196
|
+
If you want to use all the icons you can import it like:
|
|
1197
|
+
\`import { createIcons, icons } from 'lucide';
|
|
1198
|
+
lucide.createIcons({icons});\``);if(typeof s>"u")throw new Error("`createIcons()` only works in a browser environment.");if(Array.from(s.querySelectorAll(`[${t}]`)).forEach(o=>go(o,{nameAttr:t,icons:e,attrs:n})),r&&Array.from(s.querySelectorAll("template")).forEach(c=>ac({icons:e,nameAttr:t,attrs:n,root:c.content,inTemplates:r})),t==="data-lucide"){const o=s.querySelectorAll("[icon-name]");o.length>0&&(console.warn("[Lucide] Some icons were found with the now deprecated icon-name attribute. These will still be replaced for backwards compatibility, but will no longer be supported in v1.0 and you should switch to data-lucide"),Array.from(o).forEach(c=>go(c,{nameAttr:"icon-name",icons:e,attrs:n})))}},Yv={Activity:hv,Bot:gv,ClipboardList:vv,Clock:bv,Clock3:yv,Cpu:wv,Database:_v,Download:Sv,FileUp:xv,FlaskConical:$v,FolderOpen:kv,Home:Tv,KeyRound:Av,Link:Ev,LogOut:Iv,MessageCircle:Cv,MessageSquare:Rv,MessagesSquare:Mv,Paperclip:Pv,Play:zv,PlugZap:Ov,Plus:Nv,Radio:Lv,RefreshCw:Dv,Save:jv,Search:qv,Send:Vv,Settings:Uv,Settings2:Fv,Share2:Zv,Shield:Hv,Square:Bv,Trash2:Jv,TriangleAlert:Kv,X:Xv,Users:Wv,Workflow:Gv};function Fs(e){ac({icons:Yv,attrs:{width:"16",height:"16","stroke-width":"1.8"},...e?{root:e}:{}})}const Ms=document.getElementById("app"),N=Pg(),{toast:Gt,renderToasts:Qv}=Rg(N),ri="tandem_control_panel_token";let vo=0;const ey={app:Ms,state:N,api:Ht,byId:tt,escapeHtml:we,ROUTES:Kn,providerHints:Mg,toast:Gt,addCleanup:cc,clearCleanup:Us,setRoute:Wn,renderShell:oi,refreshProviderStatus:uc,refreshIdentityStatus:pc,renderIcons:Fs};function cc(e){N.cleanup.push(e)}function Us(){for(const e of N.cleanup)try{e()}catch{}N.cleanup=[]}function lc(){try{return localStorage.getItem(ri)||""}catch{return""}}function ty(e){try{localStorage.setItem(ri,e)}catch{}}function dc(){try{localStorage.removeItem(ri)}catch{}}async function Ir(){try{const e=await Ht("/api/auth/me",{method:"GET"});N.authed=!0,N.me=e,N.client=new wm({baseUrl:"/api/engine",token:"session"}),await Promise.all([uc(),pc()])}catch{N.authed=!1,N.me=null,N.client=null,N.needsProviderOnboarding=!1,N.providerReady=!1,N.providerDefault="",N.providerConnected=[],N.providerError="",N.botName="Tandem",N.botAvatarUrl="",N.controlPanelName="Tandem Control Panel"}}async function uc(){if(!N.client){N.needsProviderOnboarding=!1,N.providerReady=!1,N.providerDefault="",N.providerDefaultModel="",N.providerConnected=[],N.providerError="";return}try{const[e,t]=await Promise.all([N.client.providers.config(),N.client.providers.catalog()]),n=String(e?.default||"").trim(),s=String(e?.providers?.[n]?.default_model||"").trim(),r=new Set(t?.connected||[]),i=!!n&&(n==="ollama"||r.has(n));N.providerDefault=n,N.providerDefaultModel=s,N.providerConnected=[...r],N.providerReady=i,N.providerError="",N.needsProviderOnboarding=!i}catch(e){N.providerReady=!1,N.providerDefault="",N.providerDefaultModel="",N.providerConnected=[],N.providerError=e instanceof Error?e.message:String(e),N.needsProviderOnboarding=!0}}async function pc(){if(!N.client){N.botName="Tandem",N.botAvatarUrl="",N.controlPanelName="Tandem Control Panel";return}try{const t=(N.client?.identity?.get?await N.client.identity.get():await Ht("/api/engine/config/identity",{method:"GET"}))?.identity||{},n=String(t?.bot?.canonical_name||t?.bot?.canonicalName||"").trim(),s=t?.bot?.aliases||{},r=String(t?.bot?.avatar_url||t?.bot?.avatarUrl||"").trim(),i=String(s?.control_panel||s?.controlPanel||"").trim();N.botName=n||"Tandem",N.botAvatarUrl=r,N.controlPanelName=i||`${N.botName} Control Panel`}catch{N.botName="Tandem",N.botAvatarUrl="",N.controlPanelName="Tandem Control Panel"}}function Wn(e){const t=ti(e,Kn),n=`#/${t}`;if(window.location.hash!==n){Cg(t);return}if(N.route=t,!N.authed){_n();return}Us(),ii({showLoading:!1})}function _n(){const e=lc();Ms.innerHTML=`
|
|
1199
|
+
<main class="mx-auto grid min-h-screen w-full max-w-3xl place-items-center p-5">
|
|
1200
|
+
<section class="tcp-panel w-full max-w-xl">
|
|
1201
|
+
<div class="mb-6 rounded-2xl border border-slate-700 bg-black/20 p-3">
|
|
1202
|
+
<svg viewBox="0 0 520 160" class="hero-svg chip-hero" aria-hidden="true">
|
|
1203
|
+
<defs>
|
|
1204
|
+
<linearGradient id="hero-trace-grad" x1="0" y1="0" x2="1" y2="0">
|
|
1205
|
+
<stop offset="0%" stop-color="#64748b" stop-opacity="0.22"></stop>
|
|
1206
|
+
<stop offset="50%" stop-color="#cbd5e1" stop-opacity="0.92"></stop>
|
|
1207
|
+
<stop offset="100%" stop-color="#64748b" stop-opacity="0.22"></stop>
|
|
1208
|
+
</linearGradient>
|
|
1209
|
+
<radialGradient id="hero-chip-core" cx="50%" cy="50%" r="60%">
|
|
1210
|
+
<stop offset="0%" stop-color="#f8fafc" stop-opacity="0.92"></stop>
|
|
1211
|
+
<stop offset="100%" stop-color="#64748b" stop-opacity="0.18"></stop>
|
|
1212
|
+
</radialGradient>
|
|
1213
|
+
<filter id="hero-chip-glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
1214
|
+
<feGaussianBlur stdDeviation="3.5" result="blur"></feGaussianBlur>
|
|
1215
|
+
<feMerge>
|
|
1216
|
+
<feMergeNode in="blur"></feMergeNode>
|
|
1217
|
+
<feMergeNode in="SourceGraphic"></feMergeNode>
|
|
1218
|
+
</feMerge>
|
|
1219
|
+
</filter>
|
|
1220
|
+
</defs>
|
|
1221
|
+
|
|
1222
|
+
<rect class="chip-board" x="24" y="24" width="472" height="112" rx="14"></rect>
|
|
1223
|
+
|
|
1224
|
+
<g class="chip-grid">
|
|
1225
|
+
<line x1="48" y1="48" x2="472" y2="48"></line>
|
|
1226
|
+
<line x1="48" y1="80" x2="472" y2="80"></line>
|
|
1227
|
+
<line x1="48" y1="112" x2="472" y2="112"></line>
|
|
1228
|
+
<line x1="92" y1="34" x2="92" y2="126"></line>
|
|
1229
|
+
<line x1="176" y1="34" x2="176" y2="126"></line>
|
|
1230
|
+
<line x1="260" y1="34" x2="260" y2="126"></line>
|
|
1231
|
+
<line x1="344" y1="34" x2="344" y2="126"></line>
|
|
1232
|
+
<line x1="428" y1="34" x2="428" y2="126"></line>
|
|
1233
|
+
</g>
|
|
1234
|
+
|
|
1235
|
+
<g class="chip-traces">
|
|
1236
|
+
<path class="chip-trace flow-east" d="M48 48 H176 V64 H220"></path>
|
|
1237
|
+
<path class="chip-trace flow-east" d="M48 112 H176 V96 H220"></path>
|
|
1238
|
+
<path class="chip-trace flow-west" d="M472 48 H344 V64 H300"></path>
|
|
1239
|
+
<path class="chip-trace flow-west" d="M472 112 H344 V96 H300"></path>
|
|
1240
|
+
<path class="chip-trace flow-south" d="M176 34 V56 H220"></path>
|
|
1241
|
+
<path class="chip-trace flow-south" d="M344 34 V56 H300"></path>
|
|
1242
|
+
<path class="chip-trace flow-north" d="M176 126 V104 H220"></path>
|
|
1243
|
+
<path class="chip-trace flow-north" d="M344 126 V104 H300"></path>
|
|
1244
|
+
</g>
|
|
1245
|
+
|
|
1246
|
+
<g class="chip-ports">
|
|
1247
|
+
<circle cx="48" cy="48" r="4"></circle>
|
|
1248
|
+
<circle cx="48" cy="112" r="4"></circle>
|
|
1249
|
+
<circle cx="472" cy="48" r="4"></circle>
|
|
1250
|
+
<circle cx="472" cy="112" r="4"></circle>
|
|
1251
|
+
<circle cx="176" cy="34" r="4"></circle>
|
|
1252
|
+
<circle cx="344" cy="34" r="4"></circle>
|
|
1253
|
+
<circle cx="176" cy="126" r="4"></circle>
|
|
1254
|
+
<circle cx="344" cy="126" r="4"></circle>
|
|
1255
|
+
</g>
|
|
1256
|
+
|
|
1257
|
+
<rect class="chip-core-shell" x="220" y="56" width="80" height="48" rx="8"></rect>
|
|
1258
|
+
<rect class="chip-core" x="232" y="68" width="56" height="24" rx="4"></rect>
|
|
1259
|
+
<line class="chip-core-wire" x1="232" y1="80" x2="288" y2="80"></line>
|
|
1260
|
+
<line class="chip-core-wire" x1="260" y1="68" x2="260" y2="92"></line>
|
|
1261
|
+
<circle class="chip-core-pulse" cx="260" cy="80" r="12"></circle>
|
|
1262
|
+
|
|
1263
|
+
<g class="chip-packet packet-east-a">
|
|
1264
|
+
<circle cx="0" cy="0" r="2.4"></circle>
|
|
1265
|
+
</g>
|
|
1266
|
+
<g class="chip-packet packet-east-b">
|
|
1267
|
+
<circle cx="0" cy="0" r="2.4"></circle>
|
|
1268
|
+
</g>
|
|
1269
|
+
<g class="chip-packet packet-west-a">
|
|
1270
|
+
<circle cx="0" cy="0" r="2.4"></circle>
|
|
1271
|
+
</g>
|
|
1272
|
+
<g class="chip-packet packet-west-b">
|
|
1273
|
+
<circle cx="0" cy="0" r="2.4"></circle>
|
|
1274
|
+
</g>
|
|
1275
|
+
<g class="chip-packet packet-south">
|
|
1276
|
+
<circle cx="0" cy="0" r="2.2"></circle>
|
|
1277
|
+
</g>
|
|
1278
|
+
<g class="chip-packet packet-north">
|
|
1279
|
+
<circle cx="0" cy="0" r="2.2"></circle>
|
|
1280
|
+
</g>
|
|
1281
|
+
</svg>
|
|
1282
|
+
</div>
|
|
1283
|
+
<h1 class="mb-1 text-4xl font-semibold tracking-tight">${we(N.controlPanelName)}</h1>
|
|
1284
|
+
<p class="tcp-subtle mb-6">Use your engine API token to unlock the full web control center.</p>
|
|
1285
|
+
<form id="login-form" class="grid gap-3">
|
|
1286
|
+
<label class="text-sm text-slate-300">Engine Token</label>
|
|
1287
|
+
<input id="token" class="tcp-input" type="password" placeholder="tk_..." autocomplete="off" value="${we(e)}" />
|
|
1288
|
+
<label class="inline-flex items-center gap-2 text-xs text-slate-400">
|
|
1289
|
+
<input id="remember-token" type="checkbox" class="h-4 w-4 accent-slate-400" checked />
|
|
1290
|
+
Remember token on this browser
|
|
1291
|
+
</label>
|
|
1292
|
+
<button id="login-btn" type="submit" class="tcp-btn-primary w-full"><i data-lucide="key-round"></i> Sign In</button>
|
|
1293
|
+
<button id="check-engine-btn" type="button" class="tcp-btn w-full"><i data-lucide="activity"></i> Check Engine Connectivity</button>
|
|
1294
|
+
<div id="login-err" class="min-h-[1.2rem] text-sm text-rose-300"></div>
|
|
1295
|
+
</form>
|
|
1296
|
+
</section>
|
|
1297
|
+
</main>
|
|
1298
|
+
`,Fs(),tt("login-form").addEventListener("submit",async t=>{t.preventDefault();const n=tt("token").value.trim(),s=!!tt("remember-token")?.checked,r=tt("login-err");if(r.textContent="",!n){r.textContent="Token is required.",Gt("warn","Engine token is required.");return}try{await Ht("/api/auth/login",{method:"POST",body:JSON.stringify({token:n})}),s?ty(n):dc(),await Ir(),Gt("ok","Signed in."),Wn("dashboard")}catch(i){const o=i instanceof Error?i.message:String(i);r.textContent=o,Gt("err",o)}}),tt("check-engine-btn").addEventListener("click",async()=>{const t=tt("login-err");t.textContent="";try{const n=await Ht("/api/system/health"),s=n.engine?.ready||n.engine?.healthy?"healthy":"unhealthy";t.textContent=`Engine check: ${s} at ${n.engineUrl}`,t.className="min-h-[1.2rem] text-sm text-lime-300",Gt(n.engine?.ready||n.engine?.healthy?"ok":"warn",`Engine ${s}: ${n.engineUrl}`)}catch(n){const s=n instanceof Error?n.message:String(n);t.textContent=s,t.className="min-h-[1.2rem] text-sm text-rose-300",Gt("err",s)}})}async function ii(e={}){const{showLoading:t=!0,animateView:n=!0}=e,s=++vo,r=tt("view");if(!r)return;if(t&&(r.innerHTML='<div class="tcp-subtle">Loading...</div>'),new Set(["chat","agents","swarm","teams"]).has(N.route)&&!N.providerReady){r.innerHTML=`
|
|
1299
|
+
<div class="tcp-card">
|
|
1300
|
+
<h3 class="tcp-title mb-2">Provider Setup Required</h3>
|
|
1301
|
+
<p class="tcp-subtle">This page requires a connected default provider/model before runs can execute.</p>
|
|
1302
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
1303
|
+
<span class="tcp-badge-warn">default: ${we(N.providerDefault||"none")}</span>
|
|
1304
|
+
<span class="tcp-badge-warn">connected: ${we(String(N.providerConnected.length))}</span>
|
|
1305
|
+
</div>
|
|
1306
|
+
<div class="mt-4 flex justify-end">
|
|
1307
|
+
<button id="goto-settings" class="tcp-btn-primary">Open Provider Setup</button>
|
|
1308
|
+
</div>
|
|
1309
|
+
</div>
|
|
1310
|
+
`;const c=tt("goto-settings");c&&c.addEventListener("click",()=>Wn("settings"));return}await(fo[N.route]||fo.dashboard)(ey),s===vo&&(Fs(tt("view")),n&&(ny(r),sy()))}function ny(e){try{if(window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches)return;Tr(e,{opacity:[.72,1]},{duration:.16,easing:"ease-out"});const t=[...e.querySelectorAll(".tcp-card, .tcp-panel, .tcp-list-item")].slice(0,24);if(!t.length)return;Tr(t,{opacity:[0,1],transform:["translateY(8px)","translateY(0px)"]},{duration:.2,easing:"ease-out",delay:Ig(.02)})}catch{}}function sy(){try{if(window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches)return;const e=document.querySelector("#nav .nav-item.active");if(!e)return;Tr(e,{opacity:[.72,1],transform:["translateX(-3px)","translateX(0px)"]},{duration:.16,easing:"ease-out"})}catch{}}function oi(){if(!N.authed){_n();return}Us(),Ms.innerHTML=`
|
|
1311
|
+
<div class="grid min-h-screen grid-cols-1 lg:grid-cols-[260px_1fr]">
|
|
1312
|
+
<aside class="border-r border-slate-700 bg-panel/90 p-4">
|
|
1313
|
+
<div class="mb-4 flex items-center gap-3 rounded-xl border border-slate-700 bg-black/20 p-3">
|
|
1314
|
+
<div class="grid h-10 w-10 place-items-center overflow-hidden rounded-xl border border-slate-600 bg-muted text-slate-200">
|
|
1315
|
+
${N.botAvatarUrl?`<img src="${we(N.botAvatarUrl)}" alt="${we(N.botName)}" class="h-full w-full object-cover" />`:'<i data-lucide="cpu"></i>'}
|
|
1316
|
+
</div>
|
|
1317
|
+
<div>
|
|
1318
|
+
<div class="text-base font-semibold">${we(N.botName)}</div>
|
|
1319
|
+
<div class="text-xs uppercase tracking-wider text-slate-400">Control Center</div>
|
|
1320
|
+
</div>
|
|
1321
|
+
</div>
|
|
1322
|
+
<nav id="nav" class="grid gap-1"></nav>
|
|
1323
|
+
<div class="mt-4 border-t border-slate-700 pt-4">
|
|
1324
|
+
<button id="logout-btn" class="tcp-btn w-full"><i data-lucide="log-out"></i> Logout</button>
|
|
1325
|
+
</div>
|
|
1326
|
+
</aside>
|
|
1327
|
+
<main class="min-w-0 p-3 md:p-4">
|
|
1328
|
+
<section id="view" class="grid h-full gap-4"></section>
|
|
1329
|
+
</main>
|
|
1330
|
+
</div>
|
|
1331
|
+
`;const e=tt("nav");e.innerHTML=Kn.map(([t,n,s])=>`
|
|
1332
|
+
<button data-route="${t}" class="nav-item ${t===N.route?"active":""}">
|
|
1333
|
+
<i data-lucide="${s}"></i><span>${n}</span>
|
|
1334
|
+
</button>
|
|
1335
|
+
`).join(""),e.querySelectorAll(".nav-item").forEach(t=>{t.addEventListener("click",()=>Wn(t.dataset.route))}),tt("logout-btn").addEventListener("click",async()=>{await Ht("/api/auth/logout",{method:"POST"}).catch(()=>{}),N.authed=!1,N.me=null,N.client=null,_n()}),Fs(Ms),Qv(),ii()}async function ry(){try{await Ht("/api/auth/me")}catch{N.authed=!1,_n()}}window.addEventListener("hashchange",()=>{const e=ti(Qa(),Kn),t=e!==N.route;if(N.route=e,!N.authed){_n();return}if(t){oi();return}Us(),ii({showLoading:!1,animateView:!1})});async function iy(){if(N.route=ti(Qa(),Kn),await Ir(),!N.authed){const t=lc().trim();if(t)try{await Ht("/api/auth/login",{method:"POST",body:JSON.stringify({token:t})}),await Ir()}catch{dc()}}if(!N.authed)return _n();oi(),N.needsProviderOnboarding&&N.route==="dashboard"&&(Gt("info","Complete provider setup to start using chat/agents."),Wn("settings"));const e=setInterval(ry,3e4);cc(()=>clearInterval(e))}iy();
|