@sulala/agent 0.1.20 → 0.1.22

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.
@@ -80,4 +80,4 @@ For more information, see https://radix-ui.com/primitives/docs/components/${r.do
80
80
  `,...u.current()});return/^[\t ]/.test(p)&&(p=hs(p.charCodeAt(0))+p.slice(1)),p=p?d+" "+p:d,a.options.closeAtx&&(p+=" "+d),h(),f(),p}qk.peek=h6;function qk(e){return e.value||""}function h6(){return"<"}Gk.peek=m6;function Gk(e,r,a,l){const s=Xm(a),u=s==='"'?"Quote":"Apostrophe",d=a.enter("image");let f=a.enter("label");const h=a.createTracker(l);let p=h.move("![");return p+=h.move(a.safe(e.alt,{before:p,after:"]",...h.current()})),p+=h.move("]("),f(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(f=a.enter("destinationLiteral"),p+=h.move("<"),p+=h.move(a.safe(e.url,{before:p,after:">",...h.current()})),p+=h.move(">")):(f=a.enter("destinationRaw"),p+=h.move(a.safe(e.url,{before:p,after:e.title?" ":")",...h.current()}))),f(),e.title&&(f=a.enter(`title${u}`),p+=h.move(" "+s),p+=h.move(a.safe(e.title,{before:p,after:s,...h.current()})),p+=h.move(s),f()),p+=h.move(")"),d(),p}function m6(){return"!"}$k.peek=p6;function $k(e,r,a,l){const s=e.referenceType,u=a.enter("imageReference");let d=a.enter("label");const f=a.createTracker(l);let h=f.move("![");const p=a.safe(e.alt,{before:h,after:"]",...f.current()});h+=f.move(p+"]["),d();const y=a.stack;a.stack=[],d=a.enter("reference");const g=a.safe(a.associationId(e),{before:h,after:"]",...f.current()});return d(),a.stack=y,u(),s==="full"||!p||p!==g?h+=f.move(g+"]"):s==="shortcut"?h=h.slice(0,-1):h+=f.move("]"),h}function p6(){return"!"}Yk.peek=g6;function Yk(e,r,a){let l=e.value||"",s="`",u=-1;for(;new RegExp("(^|[^`])"+s+"([^`]|$)").test(l);)s+="`";for(/[^ \r\n]/.test(l)&&(/^[ \r\n]/.test(l)&&/[ \r\n]$/.test(l)||/^`|`$/.test(l))&&(l=" "+l+" ");++u<a.unsafe.length;){const d=a.unsafe[u],f=a.compilePattern(d);let h;if(d.atBreak)for(;h=f.exec(l);){let p=h.index;l.charCodeAt(p)===10&&l.charCodeAt(p-1)===13&&p--,l=l.slice(0,p)+" "+l.slice(h.index+1)}}return s+l+s}function g6(){return"`"}function Vk(e,r){const a=Bm(e);return!!(!r.options.resourceLink&&e.url&&!e.title&&e.children&&e.children.length===1&&e.children[0].type==="text"&&(a===e.url||"mailto:"+a===e.url)&&/^[a-z][a-z+.-]+:/i.test(e.url)&&!/[\0- <>\u007F]/.test(e.url))}Kk.peek=x6;function Kk(e,r,a,l){const s=Xm(a),u=s==='"'?"Quote":"Apostrophe",d=a.createTracker(l);let f,h;if(Vk(e,a)){const y=a.stack;a.stack=[],f=a.enter("autolink");let g=d.move("<");return g+=d.move(a.containerPhrasing(e,{before:g,after:">",...d.current()})),g+=d.move(">"),f(),a.stack=y,g}f=a.enter("link"),h=a.enter("label");let p=d.move("[");return p+=d.move(a.containerPhrasing(e,{before:p,after:"](",...d.current()})),p+=d.move("]("),h(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(h=a.enter("destinationLiteral"),p+=d.move("<"),p+=d.move(a.safe(e.url,{before:p,after:">",...d.current()})),p+=d.move(">")):(h=a.enter("destinationRaw"),p+=d.move(a.safe(e.url,{before:p,after:e.title?" ":")",...d.current()}))),h(),e.title&&(h=a.enter(`title${u}`),p+=d.move(" "+s),p+=d.move(a.safe(e.title,{before:p,after:s,...d.current()})),p+=d.move(s),h()),p+=d.move(")"),f(),p}function x6(e,r,a){return Vk(e,a)?"<":"["}Xk.peek=y6;function Xk(e,r,a,l){const s=e.referenceType,u=a.enter("linkReference");let d=a.enter("label");const f=a.createTracker(l);let h=f.move("[");const p=a.containerPhrasing(e,{before:h,after:"]",...f.current()});h+=f.move(p+"]["),d();const y=a.stack;a.stack=[],d=a.enter("reference");const g=a.safe(a.associationId(e),{before:h,after:"]",...f.current()});return d(),a.stack=y,u(),s==="full"||!p||p!==g?h+=f.move(g+"]"):s==="shortcut"?h=h.slice(0,-1):h+=f.move("]"),h}function y6(){return"["}function Qm(e){const r=e.options.bullet||"*";if(r!=="*"&&r!=="+"&&r!=="-")throw new Error("Cannot serialize items with `"+r+"` for `options.bullet`, expected `*`, `+`, or `-`");return r}function v6(e){const r=Qm(e),a=e.options.bulletOther;if(!a)return r==="*"?"-":"*";if(a!=="*"&&a!=="+"&&a!=="-")throw new Error("Cannot serialize items with `"+a+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(a===r)throw new Error("Expected `bullet` (`"+r+"`) and `bulletOther` (`"+a+"`) to be different");return a}function b6(e){const r=e.options.bulletOrdered||".";if(r!=="."&&r!==")")throw new Error("Cannot serialize items with `"+r+"` for `options.bulletOrdered`, expected `.` or `)`");return r}function Qk(e){const r=e.options.rule||"*";if(r!=="*"&&r!=="-"&&r!=="_")throw new Error("Cannot serialize rules with `"+r+"` for `options.rule`, expected `*`, `-`, or `_`");return r}function S6(e,r,a,l){const s=a.enter("list"),u=a.bulletCurrent;let d=e.ordered?b6(a):Qm(a);const f=e.ordered?d==="."?")":".":v6(a);let h=r&&a.bulletLastUsed?d===a.bulletLastUsed:!1;if(!e.ordered){const y=e.children?e.children[0]:void 0;if((d==="*"||d==="-")&&y&&(!y.children||!y.children[0])&&a.stack[a.stack.length-1]==="list"&&a.stack[a.stack.length-2]==="listItem"&&a.stack[a.stack.length-3]==="list"&&a.stack[a.stack.length-4]==="listItem"&&a.indexStack[a.indexStack.length-1]===0&&a.indexStack[a.indexStack.length-2]===0&&a.indexStack[a.indexStack.length-3]===0&&(h=!0),Qk(a)===d&&y){let g=-1;for(;++g<e.children.length;){const v=e.children[g];if(v&&v.type==="listItem"&&v.children&&v.children[0]&&v.children[0].type==="thematicBreak"){h=!0;break}}}}h&&(d=f),a.bulletCurrent=d;const p=a.containerFlow(e,l);return a.bulletLastUsed=d,a.bulletCurrent=u,s(),p}function w6(e){const r=e.options.listItemIndent||"one";if(r!=="tab"&&r!=="one"&&r!=="mixed")throw new Error("Cannot serialize items with `"+r+"` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`");return r}function k6(e,r,a,l){const s=w6(a);let u=a.bulletCurrent||Qm(a);r&&r.type==="list"&&r.ordered&&(u=(typeof r.start=="number"&&r.start>-1?r.start:1)+(a.options.incrementListMarker===!1?0:r.children.indexOf(e))+u);let d=u.length+1;(s==="tab"||s==="mixed"&&(r&&r.type==="list"&&r.spread||e.spread))&&(d=Math.ceil(d/4)*4);const f=a.createTracker(l);f.move(u+" ".repeat(d-u.length)),f.shift(d);const h=a.enter("listItem"),p=a.indentLines(a.containerFlow(e,f.current()),y);return h(),p;function y(g,v,b){return v?(b?"":" ".repeat(d))+g:(b?u:u+" ".repeat(d-u.length))+g}}function j6(e,r,a,l){const s=a.enter("paragraph"),u=a.enter("phrasing"),d=a.containerPhrasing(e,l);return u(),s(),d}const C6=pu(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function E6(e,r,a,l){return(e.children.some(function(d){return C6(d)})?a.containerPhrasing:a.containerFlow).call(a,e,l)}function N6(e){const r=e.options.strong||"*";if(r!=="*"&&r!=="_")throw new Error("Cannot serialize strong with `"+r+"` for `options.strong`, expected `*`, or `_`");return r}Zk.peek=A6;function Zk(e,r,a,l){const s=N6(a),u=a.enter("strong"),d=a.createTracker(l),f=d.move(s+s);let h=d.move(a.containerPhrasing(e,{after:s,before:f,...d.current()}));const p=h.charCodeAt(0),y=Nc(l.before.charCodeAt(l.before.length-1),p,s);y.inside&&(h=hs(p)+h.slice(1));const g=h.charCodeAt(h.length-1),v=Nc(l.after.charCodeAt(0),g,s);v.inside&&(h=h.slice(0,-1)+hs(g));const b=d.move(s+s);return u(),a.attentionEncodeSurroundingInfo={after:v.outside,before:y.outside},f+h+b}function A6(e,r,a){return a.options.strong||"*"}function T6(e,r,a,l){return a.safe(e.value,l)}function _6(e){const r=e.options.ruleRepetition||3;if(r<3)throw new Error("Cannot serialize rules with repetition `"+r+"` for `options.ruleRepetition`, expected `3` or more");return r}function M6(e,r,a){const l=(Qk(a)+(a.options.ruleSpaces?" ":"")).repeat(_6(a));return a.options.ruleSpaces?l.slice(0,-1):l}const Jk={blockquote:e6,break:Ib,code:i6,definition:o6,emphasis:Fk,hardBreak:Ib,heading:f6,html:qk,image:Gk,imageReference:$k,inlineCode:Yk,link:Kk,linkReference:Xk,list:S6,listItem:k6,paragraph:j6,root:E6,strong:Zk,text:T6,thematicBreak:M6};function R6(){return{enter:{table:O6,tableData:Bb,tableHeader:Bb,tableRow:z6},exit:{codeText:L6,table:D6,tableData:gh,tableHeader:gh,tableRow:gh}}}function O6(e){const r=e._align;this.enter({type:"table",align:r.map(function(a){return a==="none"?null:a}),children:[]},e),this.data.inTable=!0}function D6(e){this.exit(e),this.data.inTable=void 0}function z6(e){this.enter({type:"tableRow",children:[]},e)}function gh(e){this.exit(e)}function Bb(e){this.enter({type:"tableCell",children:[]},e)}function L6(e){let r=this.resume();this.data.inTable&&(r=r.replace(/\\([\\|])/g,P6));const a=this.stack[this.stack.length-1];a.type,a.value=r,this.exit(e)}function P6(e,r){return r==="|"?r:e}function U6(e){const r=e||{},a=r.tableCellPadding,l=r.tablePipeAlign,s=r.stringLength,u=a?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:`
81
81
  `,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:v,table:d,tableCell:h,tableRow:f}};function d(b,k,j,E){return p(y(b,j,E),b.align)}function f(b,k,j,E){const C=g(b,j,E),M=p([C]);return M.slice(0,M.indexOf(`
82
82
  `))}function h(b,k,j,E){const C=j.enter("tableCell"),M=j.enter("phrasing"),O=j.containerPhrasing(b,{...E,before:u,after:u});return M(),C(),O}function p(b,k){return JL(b,{align:k,alignDelimiters:l,padding:a,stringLength:s})}function y(b,k,j){const E=b.children;let C=-1;const M=[],O=k.enter("table");for(;++C<E.length;)M[C]=g(E[C],k,j);return O(),M}function g(b,k,j){const E=b.children;let C=-1;const M=[],O=k.enter("tableRow");for(;++C<E.length;)M[C]=h(E[C],b,k,j);return O(),M}function v(b,k,j){let E=Jk.inlineCode(b,k,j);return j.stack.includes("tableCell")&&(E=E.replace(/\|/g,"\\$&")),E}}function I6(){return{exit:{taskListCheckValueChecked:Hb,taskListCheckValueUnchecked:Hb,paragraph:H6}}}function B6(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:F6}}}function Hb(e){const r=this.stack[this.stack.length-2];r.type,r.checked=e.type==="taskListCheckValueChecked"}function H6(e){const r=this.stack[this.stack.length-2];if(r&&r.type==="listItem"&&typeof r.checked=="boolean"){const a=this.stack[this.stack.length-1];a.type;const l=a.children[0];if(l&&l.type==="text"){const s=r.children;let u=-1,d;for(;++u<s.length;){const f=s[u];if(f.type==="paragraph"){d=f;break}}d===a&&(l.value=l.value.slice(1),l.value.length===0?a.children.shift():a.position&&l.position&&typeof l.position.start.offset=="number"&&(l.position.start.column++,l.position.start.offset++,a.position.start=Object.assign({},l.position.start)))}}this.exit(e)}function F6(e,r,a,l){const s=e.children[0],u=typeof e.checked=="boolean"&&s&&s.type==="paragraph",d="["+(e.checked?"x":" ")+"] ",f=a.createTracker(l);u&&f.move(d);let h=Jk.listItem(e,r,a,{...l,...f.current()});return u&&(h=h.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,p)),h;function p(y){return y+d}}function q6(){return[SL(),FL(),YL(),R6(),I6()]}function G6(e){return{extensions:[wL(),qL(e),VL(),U6(e),B6()]}}const $6={tokenize:Z6,partial:!0},Wk={tokenize:J6,partial:!0},ej={tokenize:W6,partial:!0},tj={tokenize:eP,partial:!0},Y6={tokenize:tP,partial:!0},nj={name:"wwwAutolink",tokenize:X6,previous:aj},rj={name:"protocolAutolink",tokenize:Q6,previous:lj},Lr={name:"emailAutolink",tokenize:K6,previous:ij},dr={};function V6(){return{text:dr}}let Ba=48;for(;Ba<123;)dr[Ba]=Lr,Ba++,Ba===58?Ba=65:Ba===91&&(Ba=97);dr[43]=Lr;dr[45]=Lr;dr[46]=Lr;dr[95]=Lr;dr[72]=[Lr,rj];dr[104]=[Lr,rj];dr[87]=[Lr,nj];dr[119]=[Lr,nj];function K6(e,r,a){const l=this;let s,u;return d;function d(g){return!Yh(g)||!ij.call(l,l.previous)||Zm(l.events)?a(g):(e.enter("literalAutolink"),e.enter("literalAutolinkEmail"),f(g))}function f(g){return Yh(g)?(e.consume(g),f):g===64?(e.consume(g),h):a(g)}function h(g){return g===46?e.check(Y6,y,p)(g):g===45||g===95||Jt(g)?(u=!0,e.consume(g),h):y(g)}function p(g){return e.consume(g),s=!0,h}function y(g){return u&&s&&nn(l.previous)?(e.exit("literalAutolinkEmail"),e.exit("literalAutolink"),r(g)):a(g)}}function X6(e,r,a){const l=this;return s;function s(d){return d!==87&&d!==119||!aj.call(l,l.previous)||Zm(l.events)?a(d):(e.enter("literalAutolink"),e.enter("literalAutolinkWww"),e.check($6,e.attempt(Wk,e.attempt(ej,u),a),a)(d))}function u(d){return e.exit("literalAutolinkWww"),e.exit("literalAutolink"),r(d)}}function Q6(e,r,a){const l=this;let s="",u=!1;return d;function d(g){return(g===72||g===104)&&lj.call(l,l.previous)&&!Zm(l.events)?(e.enter("literalAutolink"),e.enter("literalAutolinkHttp"),s+=String.fromCodePoint(g),e.consume(g),f):a(g)}function f(g){if(nn(g)&&s.length<5)return s+=String.fromCodePoint(g),e.consume(g),f;if(g===58){const v=s.toLowerCase();if(v==="http"||v==="https")return e.consume(g),h}return a(g)}function h(g){return g===47?(e.consume(g),u?p:(u=!0,h)):a(g)}function p(g){return g===null||jc(g)||ft(g)||Ga(g)||fu(g)?a(g):e.attempt(Wk,e.attempt(ej,y),a)(g)}function y(g){return e.exit("literalAutolinkHttp"),e.exit("literalAutolink"),r(g)}}function Z6(e,r,a){let l=0;return s;function s(d){return(d===87||d===119)&&l<3?(l++,e.consume(d),s):d===46&&l===3?(e.consume(d),u):a(d)}function u(d){return d===null?a(d):r(d)}}function J6(e,r,a){let l,s,u;return d;function d(p){return p===46||p===95?e.check(tj,h,f)(p):p===null||ft(p)||Ga(p)||p!==45&&fu(p)?h(p):(u=!0,e.consume(p),d)}function f(p){return p===95?l=!0:(s=l,l=void 0),e.consume(p),d}function h(p){return s||l||!u?a(p):r(p)}}function W6(e,r){let a=0,l=0;return s;function s(d){return d===40?(a++,e.consume(d),s):d===41&&l<a?u(d):d===33||d===34||d===38||d===39||d===41||d===42||d===44||d===46||d===58||d===59||d===60||d===63||d===93||d===95||d===126?e.check(tj,r,u)(d):d===null||ft(d)||Ga(d)?r(d):(e.consume(d),s)}function u(d){return d===41&&l++,e.consume(d),s}}function eP(e,r,a){return l;function l(f){return f===33||f===34||f===39||f===41||f===42||f===44||f===46||f===58||f===59||f===63||f===95||f===126?(e.consume(f),l):f===38?(e.consume(f),u):f===93?(e.consume(f),s):f===60||f===null||ft(f)||Ga(f)?r(f):a(f)}function s(f){return f===null||f===40||f===91||ft(f)||Ga(f)?r(f):l(f)}function u(f){return nn(f)?d(f):a(f)}function d(f){return f===59?(e.consume(f),l):nn(f)?(e.consume(f),d):a(f)}}function tP(e,r,a){return l;function l(u){return e.consume(u),s}function s(u){return Jt(u)?a(u):r(u)}}function aj(e){return e===null||e===40||e===42||e===95||e===91||e===93||e===126||ft(e)}function lj(e){return!nn(e)}function ij(e){return!(e===47||Yh(e))}function Yh(e){return e===43||e===45||e===46||e===95||Jt(e)}function Zm(e){let r=e.length,a=!1;for(;r--;){const l=e[r][1];if((l.type==="labelLink"||l.type==="labelImage")&&!l._balanced){a=!0;break}if(l._gfmAutolinkLiteralWalkedInto){a=!1;break}}return e.length>0&&!a&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),a}const nP={tokenize:uP,partial:!0};function rP(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:sP,continuation:{tokenize:oP},exit:cP}},text:{91:{name:"gfmFootnoteCall",tokenize:iP},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:aP,resolveTo:lP}}}}function aP(e,r,a){const l=this;let s=l.events.length;const u=l.parser.gfmFootnotes||(l.parser.gfmFootnotes=[]);let d;for(;s--;){const h=l.events[s][1];if(h.type==="labelImage"){d=h;break}if(h.type==="gfmFootnoteCall"||h.type==="labelLink"||h.type==="label"||h.type==="image"||h.type==="link")break}return f;function f(h){if(!d||!d._balanced)return a(h);const p=Vn(l.sliceSerialize({start:d.end,end:l.now()}));return p.codePointAt(0)!==94||!u.includes(p.slice(1))?a(h):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(h),e.exit("gfmFootnoteCallLabelMarker"),r(h))}}function lP(e,r){let a=e.length;for(;a--;)if(e[a][1].type==="labelImage"&&e[a][0]==="enter"){e[a][1];break}e[a+1][1].type="data",e[a+3][1].type="gfmFootnoteCallLabelMarker";const l={type:"gfmFootnoteCall",start:Object.assign({},e[a+3][1].start),end:Object.assign({},e[e.length-1][1].end)},s={type:"gfmFootnoteCallMarker",start:Object.assign({},e[a+3][1].end),end:Object.assign({},e[a+3][1].end)};s.end.column++,s.end.offset++,s.end._bufferIndex++;const u={type:"gfmFootnoteCallString",start:Object.assign({},s.end),end:Object.assign({},e[e.length-1][1].start)},d={type:"chunkString",contentType:"string",start:Object.assign({},u.start),end:Object.assign({},u.end)},f=[e[a+1],e[a+2],["enter",l,r],e[a+3],e[a+4],["enter",s,r],["exit",s,r],["enter",u,r],["enter",d,r],["exit",d,r],["exit",u,r],e[e.length-2],e[e.length-1],["exit",l,r]];return e.splice(a,e.length-a+1,...f),e}function iP(e,r,a){const l=this,s=l.parser.gfmFootnotes||(l.parser.gfmFootnotes=[]);let u=0,d;return f;function f(g){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(g),e.exit("gfmFootnoteCallLabelMarker"),h}function h(g){return g!==94?a(g):(e.enter("gfmFootnoteCallMarker"),e.consume(g),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",p)}function p(g){if(u>999||g===93&&!d||g===null||g===91||ft(g))return a(g);if(g===93){e.exit("chunkString");const v=e.exit("gfmFootnoteCallString");return s.includes(Vn(l.sliceSerialize(v)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(g),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),r):a(g)}return ft(g)||(d=!0),u++,e.consume(g),g===92?y:p}function y(g){return g===91||g===92||g===93?(e.consume(g),u++,p):p(g)}}function sP(e,r,a){const l=this,s=l.parser.gfmFootnotes||(l.parser.gfmFootnotes=[]);let u,d=0,f;return h;function h(k){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(k),e.exit("gfmFootnoteDefinitionLabelMarker"),p}function p(k){return k===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(k),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",y):a(k)}function y(k){if(d>999||k===93&&!f||k===null||k===91||ft(k))return a(k);if(k===93){e.exit("chunkString");const j=e.exit("gfmFootnoteDefinitionLabelString");return u=Vn(l.sliceSerialize(j)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(k),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),v}return ft(k)||(f=!0),d++,e.consume(k),k===92?g:y}function g(k){return k===91||k===92||k===93?(e.consume(k),d++,y):y(k)}function v(k){return k===58?(e.enter("definitionMarker"),e.consume(k),e.exit("definitionMarker"),s.includes(u)||s.push(u),Xe(e,b,"gfmFootnoteDefinitionWhitespace")):a(k)}function b(k){return r(k)}}function oP(e,r,a){return e.check(js,r,e.attempt(nP,r,a))}function cP(e){e.exit("gfmFootnoteDefinition")}function uP(e,r,a){const l=this;return Xe(e,s,"gfmFootnoteDefinitionIndent",5);function s(u){const d=l.events[l.events.length-1];return d&&d[1].type==="gfmFootnoteDefinitionIndent"&&d[2].sliceSerialize(d[1],!0).length===4?r(u):a(u)}}function dP(e){let a=(e||{}).singleTilde;const l={name:"strikethrough",tokenize:u,resolveAll:s};return a==null&&(a=!0),{text:{126:l},insideSpan:{null:[l]},attentionMarkers:{null:[126]}};function s(d,f){let h=-1;for(;++h<d.length;)if(d[h][0]==="enter"&&d[h][1].type==="strikethroughSequenceTemporary"&&d[h][1]._close){let p=h;for(;p--;)if(d[p][0]==="exit"&&d[p][1].type==="strikethroughSequenceTemporary"&&d[p][1]._open&&d[h][1].end.offset-d[h][1].start.offset===d[p][1].end.offset-d[p][1].start.offset){d[h][1].type="strikethroughSequence",d[p][1].type="strikethroughSequence";const y={type:"strikethrough",start:Object.assign({},d[p][1].start),end:Object.assign({},d[h][1].end)},g={type:"strikethroughText",start:Object.assign({},d[p][1].end),end:Object.assign({},d[h][1].start)},v=[["enter",y,f],["enter",d[p][1],f],["exit",d[p][1],f],["enter",g,f]],b=f.parser.constructs.insideSpan.null;b&&An(v,v.length,0,hu(b,d.slice(p+1,h),f)),An(v,v.length,0,[["exit",g,f],["enter",d[h][1],f],["exit",d[h][1],f],["exit",y,f]]),An(d,p-1,h-p+3,v),h=p+v.length-2;break}}for(h=-1;++h<d.length;)d[h][1].type==="strikethroughSequenceTemporary"&&(d[h][1].type="data");return d}function u(d,f,h){const p=this.previous,y=this.events;let g=0;return v;function v(k){return p===126&&y[y.length-1][1].type!=="characterEscape"?h(k):(d.enter("strikethroughSequenceTemporary"),b(k))}function b(k){const j=Xl(p);if(k===126)return g>1?h(k):(d.consume(k),g++,b);if(g<2&&!a)return h(k);const E=d.exit("strikethroughSequenceTemporary"),C=Xl(k);return E._open=!C||C===2&&!!j,E._close=!j||j===2&&!!C,f(k)}}}class fP{constructor(){this.map=[]}add(r,a,l){hP(this,r,a,l)}consume(r){if(this.map.sort(function(u,d){return u[0]-d[0]}),this.map.length===0)return;let a=this.map.length;const l=[];for(;a>0;)a-=1,l.push(r.slice(this.map[a][0]+this.map[a][1]),this.map[a][2]),r.length=this.map[a][0];l.push(r.slice()),r.length=0;let s=l.pop();for(;s;){for(const u of s)r.push(u);s=l.pop()}this.map.length=0}}function hP(e,r,a,l){let s=0;if(!(a===0&&l.length===0)){for(;s<e.map.length;){if(e.map[s][0]===r){e.map[s][1]+=a,e.map[s][2].push(...l);return}s+=1}e.map.push([r,a,l])}}function mP(e,r){let a=!1;const l=[];for(;r<e.length;){const s=e[r];if(a){if(s[0]==="enter")s[1].type==="tableContent"&&l.push(e[r+1][1].type==="tableDelimiterMarker"?"left":"none");else if(s[1].type==="tableContent"){if(e[r-1][1].type==="tableDelimiterMarker"){const u=l.length-1;l[u]=l[u]==="left"?"center":"right"}}else if(s[1].type==="tableDelimiterRow")break}else s[0]==="enter"&&s[1].type==="tableDelimiterRow"&&(a=!0);r+=1}return l}function pP(){return{flow:{null:{name:"table",tokenize:gP,resolveAll:xP}}}}function gP(e,r,a){const l=this;let s=0,u=0,d;return f;function f(U){let ne=l.events.length-1;for(;ne>-1;){const le=l.events[ne][1].type;if(le==="lineEnding"||le==="linePrefix")ne--;else break}const W=ne>-1?l.events[ne][1].type:null,ce=W==="tableHead"||W==="tableRow"?R:h;return ce===R&&l.parser.lazy[l.now().line]?a(U):ce(U)}function h(U){return e.enter("tableHead"),e.enter("tableRow"),p(U)}function p(U){return U===124||(d=!0,u+=1),y(U)}function y(U){return U===null?a(U):Te(U)?u>1?(u=0,l.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(U),e.exit("lineEnding"),b):a(U):$e(U)?Xe(e,y,"whitespace")(U):(u+=1,d&&(d=!1,s+=1),U===124?(e.enter("tableCellDivider"),e.consume(U),e.exit("tableCellDivider"),d=!0,y):(e.enter("data"),g(U)))}function g(U){return U===null||U===124||ft(U)?(e.exit("data"),y(U)):(e.consume(U),U===92?v:g)}function v(U){return U===92||U===124?(e.consume(U),g):g(U)}function b(U){return l.interrupt=!1,l.parser.lazy[l.now().line]?a(U):(e.enter("tableDelimiterRow"),d=!1,$e(U)?Xe(e,k,"linePrefix",l.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(U):k(U))}function k(U){return U===45||U===58?E(U):U===124?(d=!0,e.enter("tableCellDivider"),e.consume(U),e.exit("tableCellDivider"),j):D(U)}function j(U){return $e(U)?Xe(e,E,"whitespace")(U):E(U)}function E(U){return U===58?(u+=1,d=!0,e.enter("tableDelimiterMarker"),e.consume(U),e.exit("tableDelimiterMarker"),C):U===45?(u+=1,C(U)):U===null||Te(U)?T(U):D(U)}function C(U){return U===45?(e.enter("tableDelimiterFiller"),M(U)):D(U)}function M(U){return U===45?(e.consume(U),M):U===58?(d=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(U),e.exit("tableDelimiterMarker"),O):(e.exit("tableDelimiterFiller"),O(U))}function O(U){return $e(U)?Xe(e,T,"whitespace")(U):T(U)}function T(U){return U===124?k(U):U===null||Te(U)?!d||s!==u?D(U):(e.exit("tableDelimiterRow"),e.exit("tableHead"),r(U)):D(U)}function D(U){return a(U)}function R(U){return e.enter("tableRow"),P(U)}function P(U){return U===124?(e.enter("tableCellDivider"),e.consume(U),e.exit("tableCellDivider"),P):U===null||Te(U)?(e.exit("tableRow"),r(U)):$e(U)?Xe(e,P,"whitespace")(U):(e.enter("data"),B(U))}function B(U){return U===null||U===124||ft(U)?(e.exit("data"),P(U)):(e.consume(U),U===92?$:B)}function $(U){return U===92||U===124?(e.consume(U),B):B(U)}}function xP(e,r){let a=-1,l=!0,s=0,u=[0,0,0,0],d=[0,0,0,0],f=!1,h=0,p,y,g;const v=new fP;for(;++a<e.length;){const b=e[a],k=b[1];b[0]==="enter"?k.type==="tableHead"?(f=!1,h!==0&&(Fb(v,r,h,p,y),y=void 0,h=0),p={type:"table",start:Object.assign({},k.start),end:Object.assign({},k.end)},v.add(a,0,[["enter",p,r]])):k.type==="tableRow"||k.type==="tableDelimiterRow"?(l=!0,g=void 0,u=[0,0,0,0],d=[0,a+1,0,0],f&&(f=!1,y={type:"tableBody",start:Object.assign({},k.start),end:Object.assign({},k.end)},v.add(a,0,[["enter",y,r]])),s=k.type==="tableDelimiterRow"?2:y?3:1):s&&(k.type==="data"||k.type==="tableDelimiterMarker"||k.type==="tableDelimiterFiller")?(l=!1,d[2]===0&&(u[1]!==0&&(d[0]=d[1],g=nc(v,r,u,s,void 0,g),u=[0,0,0,0]),d[2]=a)):k.type==="tableCellDivider"&&(l?l=!1:(u[1]!==0&&(d[0]=d[1],g=nc(v,r,u,s,void 0,g)),u=d,d=[u[1],a,0,0])):k.type==="tableHead"?(f=!0,h=a):k.type==="tableRow"||k.type==="tableDelimiterRow"?(h=a,u[1]!==0?(d[0]=d[1],g=nc(v,r,u,s,a,g)):d[1]!==0&&(g=nc(v,r,d,s,a,g)),s=0):s&&(k.type==="data"||k.type==="tableDelimiterMarker"||k.type==="tableDelimiterFiller")&&(d[3]=a)}for(h!==0&&Fb(v,r,h,p,y),v.consume(r.events),a=-1;++a<r.events.length;){const b=r.events[a];b[0]==="enter"&&b[1].type==="table"&&(b[1]._align=mP(r.events,a))}return e}function nc(e,r,a,l,s,u){const d=l===1?"tableHeader":l===2?"tableDelimiter":"tableData",f="tableContent";a[0]!==0&&(u.end=Object.assign({},Il(r.events,a[0])),e.add(a[0],0,[["exit",u,r]]));const h=Il(r.events,a[1]);if(u={type:d,start:Object.assign({},h),end:Object.assign({},h)},e.add(a[1],0,[["enter",u,r]]),a[2]!==0){const p=Il(r.events,a[2]),y=Il(r.events,a[3]),g={type:f,start:Object.assign({},p),end:Object.assign({},y)};if(e.add(a[2],0,[["enter",g,r]]),l!==2){const v=r.events[a[2]],b=r.events[a[3]];if(v[1].end=Object.assign({},b[1].end),v[1].type="chunkText",v[1].contentType="text",a[3]>a[2]+1){const k=a[2]+1,j=a[3]-a[2]-1;e.add(k,j,[])}}e.add(a[3]+1,0,[["exit",g,r]])}return s!==void 0&&(u.end=Object.assign({},Il(r.events,s)),e.add(s,0,[["exit",u,r]]),u=void 0),u}function Fb(e,r,a,l,s){const u=[],d=Il(r.events,a);s&&(s.end=Object.assign({},d),u.push(["exit",s,r])),l.end=Object.assign({},d),u.push(["exit",l,r]),e.add(a+1,0,u)}function Il(e,r){const a=e[r],l=a[0]==="enter"?"start":"end";return a[1][l]}const yP={name:"tasklistCheck",tokenize:bP};function vP(){return{text:{91:yP}}}function bP(e,r,a){const l=this;return s;function s(h){return l.previous!==null||!l._gfmTasklistFirstContentOfListItem?a(h):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(h),e.exit("taskListCheckMarker"),u)}function u(h){return ft(h)?(e.enter("taskListCheckValueUnchecked"),e.consume(h),e.exit("taskListCheckValueUnchecked"),d):h===88||h===120?(e.enter("taskListCheckValueChecked"),e.consume(h),e.exit("taskListCheckValueChecked"),d):a(h)}function d(h){return h===93?(e.enter("taskListCheckMarker"),e.consume(h),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),f):a(h)}function f(h){return Te(h)?r(h):$e(h)?e.check({tokenize:SP},r,a)(h):a(h)}}function SP(e,r,a){return Xe(e,l,"whitespace");function l(s){return s===null?a(s):r(s)}}function wP(e){return xk([V6(),rP(),dP(e),pP(),vP()])}const kP={};function qb(e){const r=this,a=e||kP,l=r.data(),s=l.micromarkExtensions||(l.micromarkExtensions=[]),u=l.fromMarkdownExtensions||(l.fromMarkdownExtensions=[]),d=l.toMarkdownExtensions||(l.toMarkdownExtensions=[]);s.push(wP(a)),u.push(q6()),d.push(G6(a))}function jP(e){return e.filter(r=>r.connections.length>0).map(r=>r.id)}const sj=[{id:"summarize_inbox",title:"Summarize my inbox",description:"Get a brief summary of unread emails",base_prompt:"Summarize my unread emails and list the most important ones with senders and subjects.",required_integrations:["gmail"],optional_integrations:[]},{id:"create_linear_issue",title:"Create a Linear issue",description:"Turn a short description into a Linear issue",base_prompt:"Create a Linear issue from this: [describe the issue]. Use the default team and set a sensible title and description.",required_integrations:["linear"],optional_integrations:["slack"]},{id:"schedule_zoom",title:"Schedule a Zoom meeting",description:"Create a Zoom meeting and optionally invite via Slack",base_prompt:"Schedule a Zoom meeting for [time/topic]. Create the meeting and share the link.",required_integrations:["zoom"],optional_integrations:["slack","calendar"]},{id:"stripe_overview",title:"Stripe overview",description:"See recent customers and revenue",base_prompt:"Give me a short overview of my Stripe account: recent customers, revenue this month, and any failed payments.",required_integrations:["stripe"],optional_integrations:[]}];function CP({connectedIds:e,onSelectIdea:r,onMissingIntegrations:a}){const l=s=>{s.required_integrations.filter(d=>!e.includes(d)).length===0?r(s):a(s)};return c.jsxs("div",{className:"flex flex-col gap-1.5",children:[c.jsx("p",{className:"text-muted-foreground text-xs font-medium",children:"Automation ideas"}),c.jsx("div",{className:"flex gap-2 overflow-x-auto pb-1 scrollbar-thin",children:sj.map(s=>c.jsxs("button",{type:"button",onClick:()=>l(s),className:"border-input bg-muted/30 hover:bg-muted/50 flex shrink-0 flex-col items-start gap-0.5 rounded-lg border px-3 py-2 text-left text-sm transition-colors min-w-[180px] max-w-[220px]",children:[c.jsx("span",{className:"font-medium",children:s.title}),c.jsx("span",{className:"text-muted-foreground line-clamp-2 text-xs",children:s.description})]},s.id))})]})}const vt="https://cdn.simpleicons.org",oj=[{id:"github",name:"GitHub",description:"Repos, issues, and code",category:"featured",icon:HR,logoUrl:`${vt}/github`},{id:"gmail",name:"Gmail",description:"Send and read email",category:"featured",icon:Vv,logoUrl:`${vt}/gmail`},{id:"notion",name:"Notion",description:"Pages, databases, and docs",category:"featured",icon:YS,logoUrl:`${vt}/notion`},{id:"slack",name:"Slack",description:"Channels and messages",category:"featured",icon:ns,logoUrl:`${vt}/slack`},{id:"calendar",name:"Google Calendar",description:"Events and scheduling",category:"featured",icon:dR,logoUrl:`${vt}/googlecalendar`},{id:"drive",name:"Google Drive",description:"Files and folders",category:"featured",icon:ZS,logoUrl:`${vt}/googledrive`},{id:"docs",name:"Google Docs",description:"Create and edit documents",category:"featured",icon:jm,logoUrl:`${vt}/googledocs`},{id:"sheets",name:"Google Sheets",description:"Spreadsheets and data",category:"featured",icon:MO,logoUrl:`${vt}/googlesheets`},{id:"asana",name:"Asana",description:"Tasks and projects",category:"featured",icon:DO,logoUrl:`${vt}/asana`},{id:"contacts",name:"Google Contacts",description:"Contacts and people",category:"featured",icon:IO,logoUrl:`${vt}/google`},{id:"facebook",name:"Facebook",description:"Pages and posts",category:"featured",icon:OR,logoUrl:`${vt}/facebook`},{id:"bluesky",name:"Bluesky",description:"Posts and timeline (atproto)",category:"featured",icon:ns,logoUrl:`${vt}/bluesky`},{id:"airtable",name:"Airtable",description:"Bases, tables, and records",category:"featured",icon:QR,logoUrl:`${vt}/airtable`},{id:"linear",name:"Linear",description:"Issues and workflows",category:"featured",icon:rR,logoUrl:`${vt}/linear`},{id:"zoom",name:"Zoom",description:"Meetings and video",category:"featured",icon:HO,logoUrl:`${vt}/zoom`},{id:"dropbox",name:"Dropbox",description:"Files and folders",category:"featured",icon:gR,logoUrl:`${vt}/dropbox`},{id:"jira",name:"Jira",description:"Issues and projects",category:"featured",icon:Yv,logoUrl:`${vt}/jirasoftware`},{id:"slides",name:"Google Slides",description:"Presentations and slides",category:"featured",icon:SO,logoUrl:`${vt}/googleslides`},{id:"figma",name:"Figma",description:"Design files and prototypes",category:"featured",icon:hO,logoUrl:`${vt}/figma`},{id:"trello",name:"Trello",description:"Boards, lists, and cards",category:"productivity",icon:Yv,logoUrl:`${vt}/trello`},{id:"twitter",name:"Twitter / X",description:"Post and read tweets",category:"featured",icon:ns,logoUrl:`${vt}/x`},{id:"microsoft",name:"Microsoft 365",description:"Outlook, Calendar, OneDrive",category:"featured",icon:Vv,logoUrl:`${vt}/microsoft`},{id:"zendesk",name:"Zendesk",description:"Tickets and support",category:"productivity",icon:ns,logoUrl:`${vt}/zendesk`},{id:"youtube",name:"YouTube",description:"Channels, videos, and uploads",category:"featured",icon:GO,logoUrl:`${vt}/youtube`}],EP=new Map(oj.map(e=>[e.id,e]));function NP(e){return EP.get(e.toLowerCase())??null}function rc(){return oj}function AP({open:e,onOpenChange:r,requiredIntegrations:a,connectedIds:l,ideaTitle:s,onConnect:u}){const d=a.filter(f=>l.includes(f));return c.jsx(iu,{open:e,onOpenChange:r,children:c.jsxs(su,{className:"max-w-md",showCloseButton:!0,children:[c.jsxs(ou,{children:[c.jsx(cu,{children:s?`Missing integrations: ${s}`:"Missing integrations"}),c.jsx(uu,{children:"Connect the required apps below, then try again. Do not execute the workflow until all required integrations are connected."})]}),c.jsx("ul",{className:"space-y-2 text-sm",children:a.map(f=>{const p=NP(f)?.name??f,y=d.includes(f);return c.jsxs("li",{className:"flex items-center justify-between gap-2 rounded-md border bg-muted/30 px-3 py-2",children:[c.jsxs("span",{className:"flex items-center gap-2",children:[y?c.jsx("span",{className:"text-green-600 dark:text-green-400","aria-hidden":!0,children:"✓"}):c.jsx("span",{className:"text-muted-foreground","aria-hidden":!0,children:"✗"}),p]}),!y&&c.jsx(me,{size:"sm",variant:"outline",onClick:()=>u(f),children:"Connect"})]},f)})}),c.jsx(kc,{className:"gap-2 pt-2",children:c.jsx(me,{variant:"outline",onClick:()=>r(!1),children:"Close"})})]})})}const Gb={p:({children:e})=>c.jsx("p",{className:"mb-2 last:mb-0",children:e}),h1:({children:e})=>c.jsx("h1",{className:"mb-2 mt-3 text-lg font-bold first:mt-0",children:e}),h2:({children:e})=>c.jsx("h2",{className:"mb-2 mt-3 text-base font-bold first:mt-0",children:e}),h3:({children:e})=>c.jsx("h3",{className:"mb-1 mt-2 text-sm font-bold first:mt-0",children:e}),ul:({children:e})=>c.jsx("ul",{className:"mb-2 list-inside list-disc space-y-0.5",children:e}),ol:({children:e})=>c.jsx("ol",{className:"mb-2 list-inside list-decimal space-y-0.5",children:e}),code:({className:e,children:r,...a})=>e?.includes("language-")?c.jsx("pre",{className:"mb-2 overflow-x-auto rounded bg-muted p-2 text-xs",children:c.jsx("code",{className:e,...a,children:r})}):c.jsx("code",{className:"rounded bg-muted px-1 py-0.5 font-mono text-xs",...a,children:r}),a:({href:e,children:r})=>c.jsx("a",{href:e,className:"text-primary underline hover:no-underline",target:"_blank",rel:"noopener noreferrer",children:r}),blockquote:({children:e})=>c.jsx("blockquote",{className:"my-2 border-l-2 border-muted-foreground/30 pl-3 italic",children:e}),img:({src:e,alt:r})=>e?c.jsx("img",{src:e,alt:r??"attachment",className:"my-1 max-h-48 max-w-full rounded object-contain"}):null};function TP(e){return e?e.replace(/\[Attached media \(use these URLs when posting images[^\]]*\):\s*([^\]]+)\]/,(r,a)=>a.split(",").map(l=>l.trim()).filter(Boolean).map(l=>`![attached](${l})`).join(`
83
- `)):""}function _P({message:e,isLast:r,isStreaming:a}){const l=e,s=l.created_at?ek(l.created_at):null,u=l.usage,d=u&&((u.prompt_tokens??0)>0||(u.completion_tokens??0)>0);if(l.role==="user"){const f=TP(l.content);return c.jsxs("div",{className:"flex items-start gap-2 justify-end",children:[c.jsxs("div",{className:"border-border bg-muted/30 flex max-w-[min(85%,42rem)] flex-col gap-0.5 rounded-lg rounded-tr-sm px-3 py-2 text-sm",children:[c.jsx("div",{className:"chat-markdown text-foreground break-words [&>*:last-child]:mb-0",children:c.jsx(zb,{remarkPlugins:[qb],components:Gb,children:f})}),s&&c.jsx("div",{className:"text-muted-foreground text-right text-xs",children:s})]}),c.jsx(W4,{className:"size-8 shrink-0",children:c.jsx(eD,{className:"rounded-full",children:c.jsx(PO,{className:"size-4"})})})]})}if(l.role==="assistant")return c.jsxs("div",{className:"flex items-start gap-2",children:[c.jsxs("div",{className:"size-8 shrink-0 flex items-center justify-center overflow-hidden rounded-full bg-muted",children:[c.jsx("img",{src:"/icon.svg",alt:"",className:"size-5 dark:hidden","aria-hidden":!0}),c.jsx("img",{src:"/logo_white.svg",alt:"",className:"size-5 hidden dark:block","aria-hidden":!0})]}),c.jsxs("div",{className:"border-border bg-muted/30 flex max-w-[min(85%,42rem)] flex-1 flex-col gap-0.5 rounded-lg rounded-tl-sm px-3 py-2 text-sm",children:[(l.thinking??"")&&c.jsxs("details",{className:"text-muted-foreground border-border mb-2 rounded border border-dashed py-1.5 pl-2 pr-2 text-xs",open:a,children:[c.jsxs("summary",{className:"cursor-pointer font-medium flex items-center gap-2",children:["Thinking",a&&c.jsx(zh,{className:"ml-1"})]}),c.jsx("pre",{className:"mt-1.5 whitespace-pre-wrap break-words font-sans",children:l.thinking})]}),l.content??""?c.jsxs("div",{className:"flex items-end gap-x-1",children:[c.jsx("div",{className:"chat-markdown text-foreground min-w-0 flex-1 [&>*:last-child]:mb-0",children:c.jsx(zb,{remarkPlugins:[qb],components:Gb,children:String(l.content)})}),a&&c.jsx(tD,{className:"shrink-0"})]}):a&&r?c.jsx(zh,{}):null,l.tool_calls?.length?c.jsxs("details",{className:"text-muted-foreground mt-1 text-xs group/details",children:[c.jsxs("summary",{className:"cursor-pointer list-none flex items-center gap-1 opacity-80 hover:opacity-100 [&::-webkit-details-marker]:hidden",children:[c.jsx(zr,{className:"size-3.5 shrink-0 transition-transform group-open/details:rotate-90"}),c.jsx("span",{children:"Show details"}),c.jsxs("span",{className:"opacity-75",children:["(",l.tool_calls.length," tool call",l.tool_calls.length!==1?"s":"",")"]})]}),c.jsx("div",{className:"mt-1.5 border-l border-border/50 pl-4",children:c.jsxs("div",{className:"opacity-80",children:["Tool calls:"," ",l.tool_calls.map(f=>`${f.name}(${f.arguments?.slice(0,40)??""}${(f.arguments?.length??0)>40?"…":""})`).join(", ")]})})]}):null,s||d||l.cost_usd!=null&&l.cost_usd>0?c.jsxs("div",{className:"text-muted-foreground mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs opacity-80",children:[s&&c.jsx("span",{children:s}),d&&c.jsxs("span",{children:[u.prompt_tokens??0," in / ",u.completion_tokens??0," out",u.total_tokens!=null&&` (${u.total_tokens} total)`]}),l.cost_usd!=null&&l.cost_usd>0&&c.jsxs("span",{title:"Estimated cost for this response",children:["$",l.cost_usd.toFixed(6)]})]}):null]})]});if(l.role==="tool"||l.name){const f=l.name??"tool",h=String(l.content??"");return c.jsxs("details",{className:"text-muted-foreground group/tool flex gap-2 pl-10 text-xs",children:[c.jsxs("summary",{className:"cursor-pointer list-none flex flex-1 items-start gap-2 [&::-webkit-details-marker]:hidden",children:[c.jsx(zr,{className:"size-3.5 shrink-0 mt-0.5 transition-transform group-open/tool:rotate-90"}),c.jsxs("div",{className:"flex-1 min-w-0 rounded bg-muted/20 px-2 py-1",children:[c.jsxs("span",{className:"font-medium",children:["Tool result (",f,")"]}),s&&c.jsxs("span",{className:"ml-1 opacity-75",children:["· ",s]})]})]}),c.jsx("div",{className:"pl-10 pr-2 pb-1",children:c.jsx("pre",{className:"mt-1 whitespace-pre-wrap break-words rounded bg-muted/20 p-2 text-xs font-sans",children:h||"(empty)"})})]})}return null}function MP(e){const{configuredProviders:r=[],chatMessages:a,chatInput:l,setChatInput:s,chatProvider:u,setChatProvider:d,chatModel:f,setChatModel:h,chatModelsLoading:p,chatSessions:y,chatSessionsLoading:g,chatLoading:v,chatAgentSessionId:b,models:k,ollamaRunning:j,ollamaStatusLoading:E,ollamaPullState:C,checkOllama:M,handleSelectSession:O,handleChatSend:T,handleNewChat:D,pendingActionId:R,pendingActionDetails:P,pendingActionLoading:B,handleApprovePending:$,handleRejectPending:U,setLastAppliedIdea:ne,chatAttachments:W=[],setChatAttachments:ce,integrations:le=[],onNavigateToIntegrations:F,missingIntegrationsFromServer:z=null,onClearMissingIntegrationsFromServer:q}=e,[Q,Y]=S.useState(!1),[A,L]=S.useState([]),[Z,_]=S.useState(""),[ue,he]=S.useState(!1),fe=jP(le),pe=a.length===0&&l.length===0,De=se=>{s(se.base_prompt),ne?.(se)},Ee=se=>{L(se.required_integrations),_(se.title),Y(!0)},ge=se=>{Y(!1),F?.()},Me=se=>{O(se),he(!1)},ee=b&&y.length>0?y.find(se=>se.id===b)?.session_key??"Current chat":"Chat history",Re=se=>{se.required_integrations.filter(mt=>!fe.includes(mt)).length===0?De(se):Ee(se)},Be=u==="ollama"&&j===!1&&!E,ln=u==="ollama"&&C?.inProgress,Zn=u==="ollama";return c.jsxs(ot,{className:"flex flex-1 flex-col",children:[c.jsxs(St,{className:"flex flex-row items-center justify-between space-y-0",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"AI Chat"}),c.jsx(kt,{children:"Agent with sessions and tools (e.g. run_task). OpenAI supports tool calls."})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsxs(_m,{children:[c.jsx(Mm,{asChild:!0,children:c.jsxs(me,{variant:"outline",size:"sm",className:"gap-1.5",children:[c.jsx(JR,{className:"size-3.5"}),"Try an idea"]})}),c.jsx(Rm,{align:"end",className:"min-w-[220px]",children:sj.map(se=>c.jsxs(ha,{onClick:()=>Re(se),className:"flex flex-col items-start gap-0.5 py-2",children:[c.jsx("span",{className:"font-medium",children:se.title}),c.jsx("span",{className:"text-muted-foreground text-xs font-normal",children:se.description})]},se.id))})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:D,children:"New chat"})]})]}),c.jsxs(ct,{className:"flex flex-1 flex-col gap-4",children:[Be&&c.jsxs("div",{className:"bg-muted border-border flex flex-wrap items-center justify-between gap-2 rounded-lg border p-3 text-sm",children:[c.jsx("span",{children:"Ollama is not running. Set it up to use the default AI."}),c.jsxs("div",{className:"flex gap-2",children:[c.jsx(me,{variant:"outline",size:"sm",asChild:!0,children:c.jsx("a",{href:"/onboard",target:"_blank",rel:"noopener noreferrer",children:"Set up Ollama"})}),c.jsx(me,{variant:"secondary",size:"sm",onClick:M,disabled:E,children:"Check again"})]})]}),ln&&C&&c.jsxs("div",{className:"bg-primary/10 border-primary/20 flex flex-col gap-2 rounded-lg border p-3 text-sm",children:[c.jsxs("div",{className:"font-medium",children:["Pulling model ",C.model,"…"]}),C.percent>=0&&C.percent<=100&&c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("div",{className:"bg-muted h-2 flex-1 overflow-hidden rounded-full",children:c.jsx("div",{className:"bg-primary h-full transition-[width] duration-300",style:{width:`${C.percent}%`}})}),c.jsxs("span",{className:"text-muted-foreground shrink-0 text-xs",children:[C.percent,"%"]})]}),C.lastLine&&c.jsx("div",{className:"text-muted-foreground truncate font-mono text-xs",title:C.lastLine,children:C.lastLine})]}),Zn&&c.jsxs("div",{className:"bg-amber-500/10 border-amber-500/50 flex items-center gap-2 rounded-lg border p-3 text-sm",children:[c.jsx(Xv,{className:"size-4 shrink-0 text-amber-600 dark:text-amber-400","aria-hidden":!0}),c.jsx("span",{className:"text-amber-700 dark:text-amber-400",children:"Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support, switch to a cloud provider."})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsxs(Jc,{open:ue,onOpenChange:he,children:[c.jsxs(me,{variant:"outline",size:"sm",className:"gap-1.5 min-w-[140px] justify-between",onClick:()=>he(!0),disabled:g,children:[c.jsx(GR,{className:"size-3.5 shrink-0"}),c.jsx("span",{className:"truncate",children:ee})]}),c.jsxs(Wc,{side:"right",className:"flex flex-col w-full sm:max-w-md",children:[c.jsxs(eu,{children:[c.jsx(tu,{children:"Chat history"}),c.jsx(nu,{children:"Switch to a previous chat or start a new one."})]}),c.jsxs("div",{className:"flex-1 overflow-y-auto px-4 pb-4",children:[c.jsx(me,{variant:"outline",size:"sm",className:"w-full justify-start mb-2",onClick:()=>Me(""),children:"New chat"}),y.length===0&&!g&&c.jsx("p",{className:"text-muted-foreground text-sm py-2",children:"No chats yet."}),g&&c.jsxs("p",{className:"text-muted-foreground text-sm py-2 flex items-center gap-2",children:[c.jsx(vc,{className:"size-4 animate-spin"}),"Loading…"]}),c.jsx("ul",{className:"space-y-1",children:y.map(se=>c.jsx("li",{children:c.jsx("button",{type:"button",onClick:()=>Me(se.id),className:Se("w-full text-left rounded-md px-3 py-2 text-sm transition-colors",se.id===b?"bg-primary/10 text-primary font-medium":"hover:bg-muted"),children:c.jsx("span",{className:"truncate block",children:se.session_key})})},se.id))})]})]})]}),c.jsxs("select",{className:"border-input bg-background h-9 rounded-md border px-3 text-sm",value:u,onChange:se=>{const ze=se.target.value;d(ze);const mt=r.find(He=>He.id===ze);h(mt?.defaultModel||"")},children:[(r.length===0||!u||!r.some(se=>se.id===u))&&c.jsx("option",{value:"",children:r.length===0?"No provider configured":"Select provider"}),r.map(se=>c.jsx("option",{value:se.id,children:se.label},se.id))]}),c.jsxs("select",{className:"border-input bg-background min-w-[200px] rounded-md border px-3 py-2 text-sm",value:f,onChange:se=>h(se.target.value),disabled:(u==="openrouter"||u==="ollama")&&p,children:[(u==="openrouter"||u==="ollama")&&p?c.jsx("option",{value:f,children:"Loading models…"}):k.map(se=>c.jsx("option",{value:se.id,children:se.name},se.id)),(u==="openrouter"||u==="ollama")&&!p&&k.length===0&&f&&c.jsx("option",{value:f,children:f})]})]}),c.jsx(Wl,{className:"min-h-[240px] flex-1 rounded-md border p-3",children:c.jsxs("div",{className:"space-y-3",children:[a.length===0&&c.jsx("p",{className:"text-muted-foreground text-sm",children:"Send a message to start. Provider and model can be changed above."}),a.map((se,ze)=>c.jsx(_P,{message:se,isLast:ze===a.length-1,isStreaming:v&&ze===a.length-1},ze)),R&&c.jsxs(ot,{className:"border-amber-500/50 bg-amber-500/5",children:[c.jsxs(St,{className:"pb-2",children:[c.jsxs(wt,{className:"flex items-center gap-2 text-base",children:[c.jsx(Xv,{className:"size-4 text-amber-600"}),"Approve this action"]}),c.jsx(kt,{children:"The agent wants to run a tool that can change files or run commands. Approve to continue or reject to cancel."})]}),c.jsx(ct,{className:"space-y-3",children:B&&!P?c.jsxs("div",{className:"text-muted-foreground flex items-center gap-2 py-2",children:[c.jsx(vc,{className:"size-4 animate-spin"}),"Loading…"]}):c.jsxs(c.Fragment,{children:[P&&c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"font-mono text-sm font-medium",children:P.toolName}),Object.keys(P.args).length>0&&c.jsx("pre",{className:"bg-muted max-h-32 overflow-auto rounded p-2 text-xs",children:JSON.stringify(P.args,null,2)})]}),c.jsxs("div",{className:"flex gap-2",children:[c.jsxs(me,{size:"sm",onClick:$,children:[c.jsx(KS,{className:"size-4"}),"Approve"]}),c.jsxs(me,{size:"sm",variant:"destructive",onClick:U,children:[c.jsx(Sc,{className:"size-4"}),"Reject"]})]})]})})]}),v&&a.length>0&&a[a.length-1]?.role==="user"&&c.jsxs("div",{className:"flex items-start gap-2",children:[c.jsxs("div",{className:"size-8 shrink-0 flex items-center justify-center overflow-hidden rounded-full bg-muted",children:[c.jsx("img",{src:"/icon.svg",alt:"",className:"size-5 dark:hidden","aria-hidden":!0}),c.jsx("img",{src:"/logo_white.svg",alt:"",className:"size-5 hidden dark:block","aria-hidden":!0})]}),c.jsx("div",{className:"border-border bg-muted/30 flex items-center gap-2 rounded-lg rounded-tl-sm px-3 py-2 text-sm",children:c.jsx(zh,{})})]})]})}),pe&&c.jsx(CP,{connectedIds:fe,onSelectIdea:De,onMissingIntegrations:Ee}),W.length>0&&c.jsx("div",{className:"border-border flex flex-wrap gap-2 rounded-md border p-2",children:W.map((se,ze)=>c.jsxs("div",{className:"relative",children:[se.type.startsWith("image/")?c.jsx("img",{src:URL.createObjectURL(se),alt:se.name,className:"h-14 w-14 rounded object-cover"}):c.jsx("div",{className:"border-input flex h-14 w-14 items-center justify-center rounded border text-xs",children:se.name.slice(0,8)}),c.jsx("button",{type:"button",className:"absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-muted-foreground text-muted hover:bg-foreground hover:text-background",onClick:()=>ce(mt=>mt.filter((He,Ut)=>Ut!==ze)),"aria-label":"Remove attachment",children:c.jsx(Sc,{className:"h-3 w-3"})})]},`${se.name}-${ze}`))}),c.jsxs("div",{className:"flex gap-2 items-end",children:[c.jsxs("label",{className:"cursor-pointer shrink-0 rounded-md border border-input px-2 py-2 text-muted-foreground hover:bg-muted/50",children:[c.jsx("input",{type:"file",accept:"image/*,video/*,.mp4,.webm,.mov,.m4v,.avi",className:"sr-only",multiple:!0,onChange:se=>{const ze=se.target.files?Array.from(se.target.files):[];ce(mt=>[...mt,...ze]),se.target.value=""}}),c.jsx(YR,{className:"h-5 w-5","aria-hidden":!0})]}),c.jsx("textarea",{className:"border-input bg-background field-sizing-content min-h-10 max-h-48 w-full min-w-0 flex-1 resize-none rounded-md border px-3 py-2 text-sm leading-relaxed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",placeholder:"Type a message…",value:l,onChange:se=>s(se.target.value),onKeyDown:se=>{se.key==="Enter"&&!se.shiftKey&&(se.preventDefault(),T())},rows:1}),c.jsx(me,{onClick:T,disabled:v||!l.trim()&&W.length===0,children:v?"Sending…":"Send"})]}),c.jsx(AP,{open:Q||z!=null&&z.length>0,onOpenChange:se=>{se||(Y(!1),q?.())},requiredIntegrations:Q?A:z??[],connectedIds:fe,ideaTitle:Q?Z:"",onConnect:ge})]})]})}function RP(e,r){const[a,l]=S.useState([]),[s,u]=S.useState(!1),[d,f]=S.useState(null),[h,p]=S.useState(!1),[y,g]=S.useState(null),[v,b]=S.useState(void 0),[k,j]=S.useState(!1),[E,C]=S.useState(!1),M=15e3,O=S.useCallback(async()=>{u(!0),p(!1),g(null),b(void 0),j(!1),C(!1);const B=new Promise(($,U)=>{setTimeout(()=>U(new Error("Request timed out. Check that the agent and integrations service are running.")),M)});try{const $=await Promise.race([Ka(),B]),U=!!($.portalGatewayUrl?.trim()&&$.integrationsMode!=="portal");if(j(U),C($.portalOAuthConnectAvailable===!0),$.integrationsMode==="portal"){p(!0),g($.portalGatewayUrl??null);const W=$.integrationsUrl?.trim()||void 0;try{let ce;if(W)try{const{integrations:z}=await Promise.race([Ah(W),B]);ce=z.map(q=>({...q,connections:[]}))}catch{ce=rc().map(q=>({id:q.id,name:q.name,iconUrl:q.logoUrl??"",description:q.description,connections:[]}))}else ce=rc().map(q=>({id:q.id,name:q.name,iconUrl:q.logoUrl??"",description:q.description,connections:[]}));const le=new Map(ce.map(z=>[z.id,z])),{connections:F}=await Promise.race([Ow(),B]);for(const z of F){const q=z.provider||"other";let Q=le.get(q);if(!Q){const Y=q.charAt(0).toUpperCase()+q.slice(1);Q={id:q,name:Y,iconUrl:"",description:"Connected via Portal",connections:[]},le.set(q,Q),ce.push(Q)}Q.connections.push(z)}l(ce)}catch{l(rc().map(ce=>({id:ce.id,name:ce.name,iconUrl:ce.logoUrl??"",description:ce.description,connections:[],tokenOnly:ce.tokenOnly})))}u(!1);return}const ne=$.integrationsUrl?.trim()||void 0;if(b(ne),ne){const{integrations:W}=await Promise.race([Ah(ne),B]);l(W)}else l(rc().map(W=>({id:W.id,name:W.name,iconUrl:W.logoUrl??"",description:W.description,connections:[],tokenOnly:W.tokenOnly})))}catch($){r($.message),l([])}finally{u(!1)}},[r]),T=S.useRef(O);T.current=O,S.useEffect(()=>{(e==="integrations"||e==="chat")&&T.current()},[e]);const D=S.useCallback(async B=>{f(B);try{const $=typeof window<"u"?`${window.location.origin}${window.location.pathname}?page=integrations`:"";if(h){const{authUrl:U}=await Dw(B,$);window.location.href=U}else{const{authUrl:U}=await Tw(B,$,v);window.location.href=U}}catch($){r($.message),f(null)}},[h,v,r]),R=S.useCallback(async B=>{try{h?await zw(B):await _w(B,v),await O()}catch($){r($.message)}},[h,v,O,r]),P=S.useCallback(async B=>{try{const{url:$}=await Nm(B);window.open($,"_blank","noopener,noreferrer")}catch($){r($.message)}},[r]);return{integrations:a,loading:s,connectingProvider:d,integrationsManagedByPortal:h,portalGatewayUrl:y,portalUrlSetButKeyMissing:k,portalOAuthConnectAvailable:E,load:O,handleConnect:D,handleDisconnect:R,startOAuthConnect:P}}function $b(e){try{const r=JSON.parse(e),a=Array.isArray(r)?r:r&&typeof r=="object"&&"servers"in r&&Array.isArray(r.servers)?r.servers:null;if(!a)return null;const l=[];for(const s of a){const u=s&&typeof s=="object"?s:{},d=typeof u.name=="string"?u.name.trim():"",f=typeof u.command=="string"?u.command.trim():"";if(!d||!f)continue;const h=Array.isArray(u.args)?u.args.map(y=>String(y)):void 0;let p;if(u.env&&typeof u.env=="object"&&!Array.isArray(u.env)){p={};for(const[y,g]of Object.entries(u.env))typeof y=="string"&&typeof g=="string"&&(p[y]=g);Object.keys(p).length===0&&(p=void 0)}l.push({name:d,command:f,args:h,env:p})}return l}catch{return null}}function OP({onError:e}){const[r,a]=S.useState([]),[l,s]=S.useState(!0),[u,d]=S.useState(!1),[f,h]=S.useState(null),[p,y]=S.useState("form"),[g,v]=S.useState(""),b=async()=>{s(!0),h(null);try{const D=(await Mw()).servers??[];return a(D),{servers:D}}catch(T){return h(T instanceof Error?T.message:String(T)),e?.(T instanceof Error?T.message:String(T)),{servers:[]}}finally{s(!1)}};S.useEffect(()=>{b()},[]),S.useEffect(()=>{p==="json"&&v(JSON.stringify({servers:r},null,2))},[p,r]);const k=async()=>{d(!0),h(null);try{let T;if(p==="json"){const R=$b(g);if(!R){h('Invalid JSON. Use { "servers": [ { "name", "command", "args"?, "env"? } ] } or an array of servers.'),d(!1);return}T=R.map(P=>({...P,env:P.env?Object.fromEntries(Object.entries(P.env).map(([B,$])=>[B,$===""?"***":$])):void 0}))}else T=r.map(R=>({...R,env:R.env?Object.fromEntries(Object.entries(R.env).map(([P,B])=>[P,B===""?"***":B])):void 0}));await Rw(T);const{servers:D}=await b();p==="json"&&v(JSON.stringify({servers:D},null,2))}catch(T){h(T instanceof Error?T.message:String(T)),e?.(T instanceof Error?T.message:String(T))}finally{d(!1)}},j=()=>{const T=$b(g);T?.length&&a(T),y("form")},E=()=>{a(T=>[...T,{name:"",command:"npx",args:["-y","package-name"],env:{}}])},C=(T,D)=>{a(R=>{const P=[...R];return P[T]={...P[T],...D},P})},M=(T,D,R)=>{a(P=>{const B=[...P],$={...B[T].env??{}};return R===""?delete $[D]:$[D]=R,B[T]={...B[T],env:$},B})},O=T=>{a(D=>D.filter((R,P)=>P!==T))};return l?c.jsx("div",{className:"text-muted-foreground text-sm",children:"Loading MCP servers…"}):c.jsx("div",{className:"flex flex-col gap-4 max-w-2xl",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsxs(wt,{className:"flex items-center gap-2",children:[c.jsx(tw,{className:"size-5"}),"MCP Servers"]}),c.jsxs(kt,{className:"space-y-1",children:[c.jsxs("span",{className:"block",children:["Add MCP servers as an alternative to Integrations (e.g. YouTube, Twitter, Gmail with API keys). Use the form or paste JSON. Tools appear as ",c.jsx("code",{className:"rounded bg-muted px-1",children:"mcp_<name>_<tool>"}),". Config is saved to ",c.jsx("code",{className:"rounded bg-muted px-1",children:"~/.sulala/mcp.json"}),"."]}),c.jsxs("span",{className:"block",children:["Find more servers at"," ",c.jsx("a",{href:"https://mcpservers.org/",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline hover:no-underline",children:"mcpservers.org"}),"."]})]})]}),c.jsxs(ct,{className:"flex flex-col gap-4",children:[c.jsxs(au,{value:p,onValueChange:T=>{T==="form"?j():y("json")},className:"w-full",children:[c.jsxs(lu,{className:"grid w-full max-w-xs grid-cols-2",children:[c.jsx(pa,{value:"form",className:"flex items-center gap-2",children:"Form"}),c.jsxs(pa,{value:"json",className:"flex items-center gap-2",children:[c.jsx(zR,{className:"size-4"}),"JSON"]})]}),c.jsxs(Vt,{value:"json",className:"mt-4 space-y-2",children:[c.jsxs(Xt,{className:"text-muted-foreground text-sm",children:["Paste or edit config. Use ",c.jsx("code",{className:"rounded bg-muted px-1",children:'{ "servers": [ ... ] }'})," or an array of server objects."]}),c.jsx("textarea",{className:"border-input bg-background min-h-[280px] w-full rounded-md border px-3 py-2 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-ring",value:g,onChange:T=>v(T.target.value),spellCheck:!1})]}),c.jsxs(Vt,{value:"form",className:"mt-4",children:[f&&c.jsx("p",{className:"text-destructive text-sm",children:f}),r.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No MCP servers configured. Click Add server and set name, command, args, and any env keys (e.g. YOUTUBE_API_KEY)."}):c.jsx("div",{className:"flex flex-col gap-4",children:r.map((T,D)=>c.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsxs("span",{className:"font-medium text-sm",children:["Server ",D+1]}),c.jsx(me,{type:"button",variant:"ghost",size:"sm",onClick:()=>O(D),className:"text-muted-foreground hover:text-destructive",children:c.jsx(bc,{className:"size-4"})})]}),c.jsxs("div",{className:"grid gap-2 grid-cols-[auto_1fr] items-center text-sm",children:[c.jsx(Xt,{className:"text-muted-foreground",children:"Name"}),c.jsx(Et,{placeholder:"e.g. youtube",value:T.name,onChange:R=>C(D,{name:R.target.value.trim()})}),c.jsx(Xt,{className:"text-muted-foreground",children:"Command"}),c.jsx(Et,{placeholder:"e.g. npx",value:T.command,onChange:R=>C(D,{command:R.target.value.trim()})}),c.jsx(Xt,{className:"text-muted-foreground",children:"Args"}),c.jsx(Et,{placeholder:"e.g. -y, zubeid-youtube-mcp-server (comma-separated)",value:Array.isArray(T.args)?T.args.join(", "):"",onChange:R=>C(D,{args:R.target.value.split(",").map(P=>P.trim()).filter(Boolean)})})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{className:"text-muted-foreground text-sm",children:"Env (API keys, etc.)"}),c.jsxs("div",{className:"space-y-2",children:[Object.entries(T.env??{}).map(([R,P])=>c.jsxs("div",{className:"flex gap-2 items-center",children:[c.jsx(Et,{className:"flex-1 font-mono text-sm",placeholder:"KEY",value:R,readOnly:!0}),c.jsx(Et,{type:"password",className:"flex-1 font-mono text-sm",placeholder:"value",value:P==="***"?"":P,onChange:B=>M(D,R,B.target.value)}),c.jsx(me,{type:"button",variant:"ghost",size:"sm",onClick:()=>M(D,R,""),children:c.jsx(bc,{className:"size-4"})})]},R)),c.jsx(DP,{onAdd:(R,P)=>{R&&M(D,R,P)}})]})]})]},D))}),c.jsxs("div",{className:"flex gap-2",children:[c.jsxs(me,{type:"button",variant:"outline",size:"sm",onClick:E,children:[c.jsx(WS,{className:"size-4 mr-1"}),"Add server"]}),c.jsx(me,{type:"button",size:"sm",onClick:k,disabled:u,children:u?"Saving…":"Save & reload tools"})]})]})]}),p==="json"&&c.jsx("div",{className:"flex gap-2 pt-2",children:c.jsx(me,{type:"button",size:"sm",onClick:k,disabled:u,children:u?"Saving…":"Save & reload tools"})})]})]})})}function DP({onAdd:e}){const[r,a]=S.useState(""),[l,s]=S.useState(""),u=()=>{const d=r.trim();d&&(e(d,l.trim()),a(""),s(""))};return c.jsxs("div",{className:"flex gap-2 items-center",children:[c.jsx(Et,{className:"flex-1 font-mono text-sm",placeholder:"e.g. YOUTUBE_API_KEY",value:r,onChange:d=>a(d.target.value)}),c.jsx(Et,{type:"password",className:"flex-1 font-mono text-sm",placeholder:"value",value:l,onChange:d=>s(d.target.value)}),c.jsx(me,{type:"button",variant:"outline",size:"sm",onClick:u,children:"Add env"})]})}function zP({integrations:e,loading:r,connectingProvider:a,integrationsManagedByPortal:l,portalUrlSetButKeyMissing:s=!1,load:u,handleConnect:d,handleDisconnect:f,onError:h}){const[p,y]=S.useState("");S.useEffect(()=>{const b=new URLSearchParams(window.location.search),k=b.get("connectionId"),j=b.get("error"),E=b.get("oauth"),C=b.get("message");if(k||j){if(j&&h)try{h(decodeURIComponent(j))}catch{h("OAuth failed")}u();const M=new URL(window.location.href);M.searchParams.delete("connectionId"),M.searchParams.delete("error"),window.history.replaceState({},"",M.toString())}else if(E==="success"||E==="error"){E==="error"&&C&&h&&h(C==="exchange_failed"?"Token exchange failed. Check PORTAL_OAUTH_CLIENT_SECRET and redirect_uri.":C==="no_token"?"No access token in response.":C),u();const M=new URL(window.location.href);M.searchParams.delete("oauth"),M.searchParams.delete("message"),window.history.replaceState({},"",M.toString())}},[u,h]);const g=S.useMemo(()=>{const b=p.trim().toLowerCase();return b?e.filter(k=>k.name.toLowerCase().includes(b)||k.description.toLowerCase().includes(b)||k.id.toLowerCase().includes(b)):e},[e,p]),v=r&&e.length===0?c.jsxs("div",{className:"text-muted-foreground flex flex-1 items-center justify-center gap-2 py-12",children:[c.jsx(vc,{className:"size-5 animate-spin"}),c.jsx("span",{children:"Loading…"})]}):l?c.jsxs("div",{className:"flex flex-1 flex-col gap-6",children:[c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("h1",{className:"text-2xl font-semibold tracking-tight",children:"Apps"}),c.jsx(bt,{variant:"secondary",className:"rounded-full text-[10px] font-medium uppercase",children:"Beta"})]}),c.jsxs("p",{className:"text-muted-foreground text-sm",children:["Connect and disconnect apps here. Your agent uses ",c.jsx("code",{className:"rounded bg-muted px-1",children:"PORTAL_API_KEY"})," or OAuth to access them."]})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure Portal gateway and connect in ",c.jsx("strong",{children:"Settings → Portal"}),"."]}),e.length>0&&c.jsx("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-end",children:c.jsxs("div",{className:"relative w-full sm:w-64",children:[c.jsx(Kv,{className:"text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2"}),c.jsx(Et,{type:"search",placeholder:"Search apps",value:p,onChange:b=>y(b.target.value),className:"pl-9"})]})}),g.length>0?c.jsx("div",{className:"grid gap-2 sm:grid-cols-2",children:g.map(b=>c.jsx(Yb,{app:b,connecting:a===b.id,onConnect:()=>d(b.id),onDisconnect:f},b.id))}):p.trim()?c.jsx("p",{className:"text-muted-foreground py-8 text-center text-sm",children:"No apps match your search."}):c.jsx("p",{className:"text-muted-foreground py-4 text-center text-sm",children:"No connections yet. Click an app to connect."})]}):e.length===0&&!r?s?c.jsxs("div",{className:"flex flex-1 flex-col gap-4 p-4",children:[c.jsxs("div",{className:"border-amber-500/50 bg-amber-500/10 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Portal API key required"}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure Portal gateway URL and API key (or connect with OAuth) in ",c.jsx("strong",{children:"Settings → Portal"}),"."]})]}),c.jsx(me,{variant:"secondary",size:"sm",onClick:()=>u(),className:"self-start",children:"Retry"})]}):c.jsx("div",{className:"flex flex-1 flex-col gap-4 p-4",children:c.jsxs("div",{className:"border-destructive/50 bg-destructive/5 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Could not reach the integrations service"}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure ",c.jsx("strong",{children:"Settings → Portal"})," (recommended), or set ",c.jsx("code",{className:"rounded bg-muted px-1",children:"INTEGRATIONS_URL"})," in the agent .env and run the integrations service."]}),c.jsx(me,{variant:"secondary",size:"sm",onClick:()=>u(),children:"Retry"})]})}):c.jsxs("div",{className:"flex flex-1 flex-col gap-6 p-4",children:[c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("h1",{className:"text-2xl font-semibold tracking-tight",children:"Apps"}),c.jsx(bt,{variant:"secondary",className:"rounded-full text-[10px] font-medium uppercase",children:"Beta"})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Connect your favorite apps. The agent uses these via connectionId — no secrets in skills."})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Portal gateway and Connect with Sulala are in ",c.jsx("strong",{children:"Settings → Portal"}),"."]}),c.jsx("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-end",children:c.jsxs("div",{className:"relative w-full sm:w-64",children:[c.jsx(Kv,{className:"text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2"}),c.jsx(Et,{type:"search",placeholder:"Search apps",value:p,onChange:b=>y(b.target.value),className:"pl-9"})]})}),c.jsx("div",{className:"grid gap-2 sm:grid-cols-2",children:g.map(b=>c.jsx(Yb,{app:b,connecting:a===b.id,onConnect:()=>d(b.id),onDisconnect:f},b.id))}),g.length===0&&c.jsx("p",{className:"text-muted-foreground py-8 text-center text-sm",children:"No apps match your search."})]});return c.jsx("div",{className:"flex flex-1 flex-col p-4 min-h-0",children:c.jsxs(au,{defaultValue:"mcp",className:"flex flex-1 flex-col min-h-0",children:[c.jsxs(lu,{className:"w-full max-w-xs grid grid-cols-2 mb-4",children:[c.jsxs(pa,{value:"mcp",className:"flex items-center gap-2",children:[c.jsx(tw,{className:"size-4"}),"MCP Servers"]}),c.jsxs(pa,{value:"connections",className:"flex items-center gap-2",children:[c.jsx(JS,{className:"size-4"}),"Connections"]})]}),c.jsx(Vt,{value:"mcp",className:"mt-0 flex-1 data-[state=inactive]:hidden min-h-0",children:c.jsx(OP,{onError:h})}),c.jsx(Vt,{value:"connections",className:"mt-0 flex-1 data-[state=inactive]:hidden min-h-0",children:v})]})})}const LP="https://discord.com/developers/applications",PP="https://dashboard.stripe.com/apikeys";function Yb({app:e,connecting:r,onConnect:a,onDisconnect:l,portalMode:s=!1}){const u=e.connections.length>0,d=e.tokenOnly===!0,f=e.id==="discord",h=e.id==="stripe",p=()=>{if(!u){if(d&&f){window.open(LP,"_blank","noopener,noreferrer");return}if(d&&h){window.open(PP,"_blank","noopener,noreferrer");return}a()}};return c.jsxs("div",{className:"border-border hover:bg-muted/50 flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2.5 transition-colors",onClick:p,onKeyDown:y=>{(y.key==="Enter"||y.key===" ")&&(y.preventDefault(),p())},role:"button",tabIndex:0,children:[c.jsx("div",{className:"bg-muted flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg p-1.5",children:e.iconUrl?c.jsx("img",{src:e.iconUrl,alt:"",className:"size-full object-contain"}):c.jsx("span",{className:"text-muted-foreground text-sm font-medium",children:e.name.charAt(0)})}),c.jsxs("div",{className:"min-w-0 flex-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"font-medium truncate",children:e.name}),u&&c.jsx(bt,{variant:"secondary",className:"shrink-0 text-[10px]",children:"Connected"}),d&&!u&&c.jsx(bt,{variant:"outline",className:"shrink-0 text-[10px]",children:"Setup"})]}),c.jsx("p",{className:"text-muted-foreground truncate text-sm",children:e.description}),f&&d&&c.jsxs("p",{className:"text-muted-foreground mt-0.5 text-xs",children:["Set ",c.jsx("code",{className:"rounded bg-muted px-1",children:"DISCORD_BOT_TOKEN"})," in agent .env or Settings → Channels. Click to open Discord Developer Portal."]}),h&&d&&c.jsxs("p",{className:"text-muted-foreground mt-0.5 text-xs",children:["Set Secret Key in Settings → Payment or ",c.jsx("code",{className:"rounded bg-muted px-1",children:"STRIPE_SECRET_KEY"})," in agent .env. Click to open Stripe API keys."]})]}),c.jsx("div",{className:"flex shrink-0 items-center gap-1",children:u&&!s?e.connections.map(y=>c.jsx(me,{variant:"ghost",size:"icon",className:"size-8",onClick:g=>{g.stopPropagation(),l(y.id)},title:"Disconnect",children:c.jsx(bc,{className:"size-3.5 text-muted-foreground"})},y.id)):u&&s?c.jsx("span",{title:"Manage in Portal",children:c.jsx(zr,{className:"text-muted-foreground size-5"})}):r?c.jsx(vc,{className:"text-muted-foreground size-5 animate-spin"}):c.jsx(zr,{className:"text-muted-foreground size-5"})})]})}function Jm({className:e,...r}){return c.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:c.jsx("table",{"data-slot":"table",className:Se("w-full caption-bottom text-sm",e),...r})})}function Wm({className:e,...r}){return c.jsx("thead",{"data-slot":"table-header",className:Se("[&_tr]:border-b",e),...r})}function ep({className:e,...r}){return c.jsx("tbody",{"data-slot":"table-body",className:Se("[&_tr:last-child]:border-0",e),...r})}function ga({className:e,...r}){return c.jsx("tr",{"data-slot":"table-row",className:Se("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",e),...r})}function Zt({className:e,...r}){return c.jsx("th",{"data-slot":"table-head",className:Se("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...r})}function Ht({className:e,...r}){return c.jsx("td",{"data-slot":"table-cell",className:Se("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...r})}const cj=[{label:"Every day at 9:00 AM",value:"0 9 * * *"},{label:"Every day at 8:00 AM",value:"0 8 * * *"},{label:"Every day at 12:00 PM (noon)",value:"0 12 * * *"},{label:"Every day at 6:00 PM",value:"0 18 * * *"},{label:"Every hour",value:"0 * * * *"},{label:"Every 30 minutes",value:"*/30 * * * *"},{label:"Every 15 minutes",value:"*/15 * * * *"},{label:"Every Monday at 9:00 AM",value:"0 9 * * 1"},{label:"Every weekday at 9:00 AM",value:"0 9 * * 1-5"},{label:"Custom (advanced)",value:"__custom__"}];function UP(e){return cj.find(a=>a.value===e&&a.value!=="__custom__")?.label??(e?`Custom: ${e}`:"—")}function IP(e){const{schedules:r,load:a,onCreateSchedule:l,onUpdateSchedule:s,onDeleteSchedule:u,onRunSchedule:d,onFetchScheduleRuns:f}=e,[h,p]=S.useState("Morning post"),[y,g]=S.useState(""),[v,b]=S.useState("Fetch daily news and post one to Bluesky."),[k,j]=S.useState("0 9 * * *"),[E,C]=S.useState(""),[M,O]=S.useState(!0),[T,D]=S.useState(""),[R,P]=S.useState(""),[B,$]=S.useState([]),[U,ne]=S.useState([]),[W,ce]=S.useState(!1),[le,F]=S.useState(!1),[z,q]=S.useState(null),[Q,Y]=S.useState(null),[A,L]=S.useState([]),[Z,_]=S.useState(!1),[ue,he]=S.useState(null),fe=k==="__custom__"?E.trim():k;S.useEffect(()=>{Ka().then(ee=>$(ee?.aiProviders??[])).catch(()=>$([]))},[]),S.useEffect(()=>{if(!T||T!=="ollama"&&T!=="openrouter"){ne([]),P("");return}ce(!0),Ss(T).then(ee=>ne(ee.models??[])).catch(()=>ne([])).finally(()=>ce(!1))},[T]);const pe=async()=>{if(v.trim()){F(!0);try{const ee=M?[{channel:"telegram",target:"default"}]:[];await l({name:h.trim()||"Scheduled job",description:y.trim()||void 0,cron_expression:fe.trim(),prompt:v.trim(),delivery:ee.length?ee:void 0,provider:T.trim()||null,model:R.trim()||null}),p("Morning post"),g(""),b("Fetch daily news and post one to Bluesky."),j("0 9 * * *"),C(""),O(!0),D(""),P("")}finally{F(!1)}}},De=async ee=>{q(ee.id);try{await s(ee.id,{enabled:!ee.enabled})}finally{q(null)}},Ee=async ee=>{q(ee);try{await u(ee)}finally{q(null)}},ge=async ee=>{q(ee.id),he(null);try{const Re=await d(ee.id);he({jobId:ee.id,message:`Job enqueued (task ${Re.id.slice(0,12)}…)`}),a()}catch(Re){he({jobId:ee.id,message:Re instanceof Error?Re.message:"Run failed"})}finally{q(null)}},Me=ee=>{Y(ee)};return S.useEffect(()=>{if(!Q){L([]);return}_(!0),f(Q.id).then(({runs:ee})=>L(ee)).catch(()=>L([])).finally(()=>_(!1))},[Q?.id,f]),c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"New job"}),c.jsx(kt,{children:"Describe what you want in plain language. The agent will use your skills (e.g. news, Bluesky) and run on schedule. Job results are sent to Telegram: the first chat that messages the bot becomes the notification target, or set it in Settings → Channels."})]}),c.jsxs(ct,{className:"space-y-4",children:[c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Name"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:h,onChange:ee=>p(ee.target.value),placeholder:"Morning post"})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Schedule"}),c.jsx("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:k,onChange:ee=>j(ee.target.value),children:cj.map(ee=>c.jsx("option",{value:ee.value,children:ee.label},ee.value))}),k==="__custom__"&&c.jsxs("div",{className:"mt-2 space-y-1",children:[c.jsx("label",{className:"text-muted-foreground block text-xs",children:"Cron expression: minute hour day month weekday (e.g. 0 9 * * * = 9:00 daily)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 font-mono text-sm",value:E,onChange:ee=>C(ee.target.value),placeholder:"0 9 * * *"})]})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Description (optional)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:y,onChange:ee=>g(ee.target.value),placeholder:"Short context for this job"})]}),c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"AI Provider (optional)"}),c.jsxs("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:T,onChange:ee=>D(ee.target.value),children:[c.jsx("option",{value:"",children:"Use default (OpenRouter/OpenAI if configured)"}),B.map(ee=>c.jsx("option",{value:ee.id,children:ee.label},ee.id)),B.length===0&&c.jsxs(c.Fragment,{children:[c.jsx("option",{value:"",children:"Use default"}),c.jsx("option",{value:"openrouter",children:"OpenRouter"}),c.jsx("option",{value:"openai",children:"OpenAI"}),c.jsx("option",{value:"claude",children:"Claude"}),c.jsx("option",{value:"gemini",children:"Gemini"}),c.jsx("option",{value:"ollama",children:"Ollama"})]})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Leave empty to use app default (prefers OpenRouter or OpenAI when configured). Do not use Ollama for jobs unless it is always running."}),T==="ollama"&&c.jsxs("div",{className:"rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-sm text-amber-800 dark:text-amber-200",children:[c.jsx("strong",{children:"Warning:"})," Using Ollama for scheduled jobs is not recommended. The job will not run if Ollama is not running when the job triggers. Use OpenRouter or OpenAI for reliable scheduled runs."]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Model (optional)"}),T&&(T==="ollama"||T==="openrouter")?c.jsxs("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:R,onChange:ee=>P(ee.target.value),disabled:W,children:[c.jsx("option",{value:"",children:"Use provider default"}),U.map(ee=>c.jsx("option",{value:ee.id,children:ee.name},ee.id))]}):c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:R,onChange:ee=>P(ee.target.value),placeholder:T?B.find(ee=>ee.id===T)?.defaultModel??"e.g. gpt-4o-mini":"Select provider first",disabled:!T})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Prompt *"}),c.jsx("textarea",{className:"border-input bg-background min-h-[80px] w-full rounded-md border px-3 py-2 text-sm",value:v,onChange:ee=>b(ee.target.value),placeholder:"e.g. Fetch daily news and post one to Bluesky.",rows:3})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-4",children:[c.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[c.jsx("input",{type:"checkbox",checked:M,onChange:ee=>O(ee.target.checked)}),"Notify via Telegram when job completes or fails"]}),c.jsx(me,{onClick:pe,disabled:le||!v.trim()||!fe,children:le?"Adding…":"Add job"})]})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Scheduled jobs"}),c.jsx(kt,{children:"Agent jobs (prompt + schedule). You get a Telegram notification on success or failure if delivery is set."})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:a,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[320px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"Name"}),c.jsx(Zt,{children:"Prompt"}),c.jsx(Zt,{children:"Model"}),c.jsx(Zt,{children:"Cron"}),c.jsx(Zt,{children:"Delivery"}),c.jsx(Zt,{children:"Enabled"}),c.jsx(Zt,{children:"Created"}),c.jsx(Zt,{className:"w-[70px]",children:"Actions"})]})}),c.jsx(ep,{children:r.length===0?c.jsx(ga,{children:c.jsx(Ht,{colSpan:8,className:"text-muted-foreground text-center text-sm",children:"No scheduled jobs. Add one above."})}):r.map(ee=>c.jsxs(ga,{children:[c.jsx(Ht,{className:"font-medium",children:ee.name||ee.id}),c.jsx(Ht,{className:"max-w-[200px] truncate text-sm",children:ee.prompt||ee.task_type||"—"}),c.jsx(Ht,{className:"text-muted-foreground max-w-[120px] truncate text-xs",children:ee.provider?`${ee.provider}${ee.model?` / ${ee.model}`:""}`:"—"}),c.jsx(Ht,{className:"text-xs",children:UP(ee.cron_expression)}),c.jsx(Ht,{children:ee.delivery?c.jsx(bt,{variant:"outline",children:"Telegram"}):c.jsx("span",{className:"text-muted-foreground text-xs",children:"—"})}),c.jsx(Ht,{children:c.jsx(bt,{variant:ee.enabled?"default":"secondary",children:ee.enabled?"On":"Off"})}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(ee.created_at)}),c.jsx(Ht,{children:c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs(_m,{children:[c.jsx(Mm,{asChild:!0,children:c.jsx(me,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0",disabled:z===ee.id,title:"Actions",children:c.jsx(ER,{className:"size-4"})})}),c.jsxs(Rm,{align:"end",children:[c.jsxs(ha,{onClick:()=>ge(ee),children:[c.jsx(pO,{className:"size-4"}),"Test"]}),c.jsxs(ha,{onClick:()=>Me(ee),children:[c.jsx(jm,{className:"size-4"}),"Logs"]}),c.jsxs(ha,{onClick:()=>De(ee),children:[c.jsx(vO,{className:"size-4"}),ee.enabled?"Disable":"Enable"]}),c.jsxs(ha,{variant:"destructive",onClick:()=>Ee(ee.id),children:[c.jsx(bc,{className:"size-4"}),"Delete"]})]})]}),ue?.jobId===ee.id&&c.jsx("span",{className:"text-muted-foreground text-xs",children:ue.message})]})})]},ee.id))})]})})})]}),c.jsx(Jc,{open:!!Q,onOpenChange:ee=>!ee&&Y(null),children:c.jsxs(Wc,{side:"right",className:"w-full max-w-lg overflow-y-auto",children:[c.jsxs(eu,{children:[c.jsxs(tu,{children:[Q?.name||Q?.id," — Run logs"]}),c.jsx(nu,{children:"Recent runs for this job. Status: pending, running, done, or failed."})]}),c.jsx("div",{className:"mt-4 space-y-3",children:Z?c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading…"}):A.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No runs yet. Use Test to run now."}):A.map(ee=>c.jsxs("div",{className:"border-input rounded-md border p-3 text-sm",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx(bt,{variant:ee.status==="done"?"default":ee.status==="failed"?"destructive":ee.status==="running"?"secondary":"outline",children:ee.status}),c.jsxs("span",{className:"text-muted-foreground font-mono text-xs",children:[ee.id.slice(0,16),"…"]})]}),c.jsxs("p",{className:"text-muted-foreground mt-1 text-xs",children:[ek(ee.created_at),ee.finished_at!=null&&ee.started_at!=null&&c.jsxs(c.Fragment,{children:[" · ",Math.round((ee.finished_at-ee.started_at)/1e3),"s"]})]}),ee.error&&c.jsx("p",{className:"mt-2 text-destructive text-xs",children:ee.error})]},ee.id))})]})})]})}function BP({config:e}){return c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Watched folders"}),c.jsx(kt,{children:"Paths monitored by the file watcher (from env and config/watched.json). Read-only."})]}),c.jsx(ct,{children:e?.watchFolders&&e.watchFolders.length>0?c.jsx("ul",{className:"space-y-2 font-mono text-sm",children:e.watchFolders.map(r=>c.jsx("li",{className:"rounded border bg-muted/30 px-3 py-2",children:r},r))}):c.jsx("p",{className:"text-muted-foreground text-sm",children:"No watched folders configured. Set WATCH_FOLDERS in .env or add paths to config/watched.json."})})]})}function HP(e){const[r,a]=S.useState(null);return S.useEffect(()=>{(e==="config"||e==="settings")&&Ka().then(a).catch(()=>a(null))},[e]),r}const Vb={OPENAI_API_KEY:"OpenAI API Key",ANTHROPIC_API_KEY:"Anthropic (Claude) API Key",GOOGLE_GEMINI_API_KEY:"Google Gemini API Key",GEMINI_API_KEY:"Gemini API Key (alt)",OPENROUTER_API_KEY:"OpenRouter API Key",OLLAMA_BASE_URL:"Ollama Base URL",GATEWAY_API_KEY:"Gateway API Key"};function FP(){const[e,r]=S.useState({}),[a,l]=S.useState({}),[s,u]=S.useState(!0),[d,f]=S.useState(!1),[h,p]=S.useState(null),[y,g]=S.useState(!1),[v,b]=S.useState(null),[k,j]=S.useState(null),[E,C]=S.useState(""),[M,O]=S.useState(""),[T,D]=S.useState([]),[R,P]=S.useState(!1),[B,$]=S.useState(!1),[U,ne]=S.useState(null);S.useEffect(()=>{Promise.all([sr(),Kl(),Ka(),Lw()]).then(([F,z,q,Q])=>{r(F.keys||{}),p(z.running),j(q??null),C(Q.defaultProvider??""),O(Q.defaultModel??"")}).catch(()=>b({type:"error",text:"Failed to load"})).finally(()=>u(!1))},[]),S.useEffect(()=>{if(!E||E!=="ollama"&&E!=="openrouter"){D([]);return}P(!0),Ss(E).then(F=>D(F.models??[])).catch(()=>D([])).finally(()=>P(!1))},[E]);const W=async()=>{g(!0);try{const{running:F}=await Kl();p(F)}finally{g(!1)}},ce=async()=>{f(!0),b(null);try{const F={};for(const[q,Q]of Object.entries(a))typeof Q=="string"&&Q.trim()&&(F[q]=Q.trim());await bs(F);const{keys:z}=await sr();r(z),l({}),b({type:"success",text:"API keys saved. Restart the agent for changes to take effect."})}catch(F){b({type:"error",text:F instanceof Error?F.message:"Failed to save"})}finally{f(!1)}},le=Object.keys(Vb);return s?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading…"})})}):c.jsxs("div",{className:"space-y-6",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"AI Providers"}),c.jsxs(kt,{children:["Add or update API keys. Saved to ",c.jsx("code",{className:"rounded bg-muted px-1 text-xs",children:"~/.sulala/.env"}),". Restart the agent for changes."]})]}),c.jsxs(ct,{className:"space-y-4",children:[le.map(F=>c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:F,children:Vb[F]??F}),c.jsx(Et,{id:F,type:"password",placeholder:e[F]==="set"?"(already set)":"",value:a[F]??"",onChange:z=>l(q=>({...q,[F]:z.target.value})),autoComplete:"off"})]},F)),v&&c.jsx("p",{className:v.type==="success"?"text-green-600 dark:text-green-400 text-sm":"text-destructive text-sm",children:v.text}),c.jsx(me,{onClick:ce,disabled:d||Object.keys(a).length===0,children:d?"Saving…":"Save"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"Default for scheduled jobs"}),c.jsx(kt,{children:'When a job uses "Use default", this provider and model are used. Set this to OpenRouter or OpenAI (not Ollama) so jobs run reliably even when Ollama is not running.'})]}),c.jsxs(ct,{className:"space-y-4",children:[c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"job-default-provider",children:"Provider"}),c.jsxs("select",{id:"job-default-provider",className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:E,onChange:F=>{C(F.target.value),O("")},children:[c.jsx("option",{value:"",children:"Use env default"}),(k?.aiProviders??[]).filter(F=>F.id!=="ollama").map(F=>c.jsx("option",{value:F.id,children:F.label},F.id)),c.jsx("option",{value:"ollama",children:"Ollama (not recommended for jobs)"})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"job-default-model",children:"Model"}),E&&(E==="ollama"||E==="openrouter")?c.jsxs("select",{id:"job-default-model",className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:M,onChange:F=>O(F.target.value),disabled:R,children:[c.jsx("option",{value:"",children:"Use provider default"}),T.map(F=>c.jsx("option",{value:F.id,children:F.name},F.id))]}):c.jsx(Et,{id:"job-default-model",className:"h-9 text-sm",value:M,onChange:F=>O(F.target.value),placeholder:E?"e.g. gpt-4o-mini":"Set provider first",disabled:!E})]})]}),E==="ollama"&&c.jsx("p",{className:"text-amber-600 dark:text-amber-400 text-sm",children:"Ollama is not recommended for scheduled jobs. If Ollama is not running when the job runs, the job will fail."}),U&&c.jsx("p",{className:U.type==="success"?"text-green-600 dark:text-green-400 text-sm":"text-destructive text-sm",children:U.text}),c.jsx(me,{onClick:async()=>{$(!0),ne(null);try{await Pw({defaultProvider:E.trim()||null,defaultModel:M.trim()||null}),ne({type:"success",text:"Job default saved. New jobs using “Use default” will use this."})}catch(F){ne({type:"error",text:F instanceof Error?F.message:"Failed to save"})}finally{$(!1)}},disabled:B,children:B?"Saving…":"Save job default"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"Ollama"}),c.jsx(kt,{children:"Local AI. No API key required. Install from ollama.com"})]}),c.jsxs(ct,{children:[h?c.jsx("p",{className:"text-green-600 dark:text-green-400 text-sm",children:"Ollama is running."}):c.jsx("p",{className:"text-muted-foreground text-sm",children:"Ollama is not running."}),c.jsx(me,{variant:"outline",size:"sm",onClick:W,disabled:y,className:"mt-2",children:y?"Checking…":"Check again"}),c.jsxs("p",{className:"text-muted-foreground mt-2 text-xs",children:["Install from ",c.jsx("a",{href:"https://ollama.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"ollama.com"})," or run ",c.jsx("code",{children:"ollama serve"})," in terminal."]})]})]})]})}function qP(e){const{tasks:r,load:a,enqueueType:l,setEnqueueType:s,enqueuePayload:u,setEnqueuePayload:d,enqueueing:f,actionTaskId:h,handleTaskCancel:p,handleTaskRetry:y,handleEnqueue:g}=e;return c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Enqueue task"}),c.jsx(kt,{children:"Add a task to the queue"})]}),c.jsxs(ct,{className:"flex flex-wrap items-end gap-4",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Type"}),c.jsx("input",{className:"border-input bg-background h-9 rounded-md border px-3 text-sm",value:l,onChange:v=>s(v.target.value),placeholder:"e.g. heartbeat"})]}),c.jsxs("div",{className:"min-w-[200px] space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Payload (JSON)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:u,onChange:v=>d(v.target.value),placeholder:'{"key": "value"}'})]}),c.jsx(me,{onClick:g,disabled:f,children:f?"Enqueueing…":"Enqueue"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Tasks"}),c.jsx(kt,{children:"Recent tasks (from gateway)"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:a,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[400px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"ID"}),c.jsx(Zt,{children:"Type"}),c.jsx(Zt,{children:"Status"}),c.jsx(Zt,{children:"Created"}),c.jsx(Zt,{className:"w-[120px]",children:"Actions"})]})}),c.jsx(ep,{children:r.map(v=>c.jsxs(ga,{children:[c.jsxs(Ht,{className:"font-mono text-xs",children:[v.id.slice(0,20),"…"]}),c.jsx(Ht,{children:v.type}),c.jsx(Ht,{children:c.jsx(bt,{variant:v.status==="done"?"default":v.status==="failed"?"destructive":v.status==="cancelled"?"outline":"secondary",children:v.status})}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(v.created_at)}),c.jsxs(Ht,{children:[(v.status==="pending"||v.status==="running")&&c.jsx(me,{variant:"ghost",size:"sm",className:"h-7 text-destructive hover:text-destructive",disabled:h===v.id,onClick:()=>p(v.id),children:"Cancel"}),v.status==="failed"&&c.jsx(me,{variant:"ghost",size:"sm",className:"h-7",disabled:h===v.id,onClick:()=>y(v.id),children:"Retry"})]})]},v.id))})]})})})]})]})}function GP({logs:e,load:r}){return c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Logs"}),c.jsx(kt,{children:"Recent gateway and worker logs"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:r,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[500px] rounded-md border p-3",children:c.jsx("div",{className:"space-y-1 font-mono text-xs",children:e.map(a=>c.jsxs("div",{className:"flex flex-wrap gap-2 border-b py-1.5 last:border-0",children:[c.jsx("span",{className:"text-muted-foreground shrink-0",children:ws(a.created_at)}),c.jsx(bt,{variant:"outline",className:"shrink-0",children:a.source}),c.jsx("span",{className:a.level==="error"?"text-destructive":a.level==="warn"?"text-amber-600 dark:text-amber-400":"",children:a.message})]},a.id))})})})]})}function $P({fileStates:e,load:r}){return c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"File states"}),c.jsx(kt,{children:"Files seen by the watcher (last modified time, size)"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:r,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[500px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"Path"}),c.jsx(Zt,{children:"Size"}),c.jsx(Zt,{children:"Last seen"})]})}),c.jsx(ep,{children:e.length===0?c.jsx(ga,{children:c.jsx(Ht,{colSpan:3,className:"text-muted-foreground text-center",children:"No file states. Add watched folders and trigger file events."})}):e.map(a=>c.jsxs(ga,{children:[c.jsx(Ht,{className:"max-w-[400px] truncate font-mono text-xs",children:a.path}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:a.size!=null?`${a.size} B`:"—"}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(a.last_seen)})]},a.path))})]})})})]})}const YP="https://discord.com/developers/applications";function VP(){const[e,r]=S.useState(null),[a,l]=S.useState(null),[s,u]=S.useState(!0),[d,f]=S.useState(!1),[h,p]=S.useState(null),[y,g]=S.useState(!1),[v,b]=S.useState(""),[k,j]=S.useState("open"),[E,C]=S.useState(""),[M,O]=S.useState(""),[T,D]=S.useState(""),[R,P]=S.useState([]),[B,$]=S.useState(!1),[U,ne]=S.useState(null),[W,ce]=S.useState(""),[le,F]=S.useState(!1),z=async()=>{u(!0),p(null);try{const[Y,A,L]=await Promise.all([uw(),fw(),Ka()]);r(Y),ne(A),l(L),g(Y.enabled),b(""),j(Y.dmPolicy||"open"),C(Array.isArray(Y.allowFrom)?Y.allowFrom.join(", "):""),O(Y.defaultProvider??""),D(Y.defaultModel??"")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{u(!1)}};S.useEffect(()=>{z()},[]),S.useEffect(()=>{if(!M||M!=="ollama"&&M!=="openrouter"){P([]);return}$(!0),Ss(M).then(Y=>P(Y.models??[])).catch(()=>P([])).finally(()=>$(!1))},[M]);const q=async()=>{f(!0),p(null);try{const Y=E.split(/[,;\s]+/).map(Z=>parseInt(Z.trim(),10)).filter(Z=>!Number.isNaN(Z)),A={enabled:y,dmPolicy:k,allowFrom:Y,defaultProvider:M.trim()||null,defaultModel:T.trim()||null};v.trim()&&(A.botToken=v.trim());const L=await dw(A);r(L),b("")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{f(!1)}},Q=async()=>{F(!0),p(null);try{const Y=await hw({botToken:W.trim()||null});ne(Y),ce("")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{F(!1)}};return s?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading channels…"})})}):c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Telegram"}),c.jsx(kt,{children:"Connect your device to Telegram so you can chat with the agent from your phone. Create a bot with @BotFather, then paste the token below."})]}),c.jsxs(ct,{className:"space-y-4",children:[e&&c.jsxs("div",{className:"space-y-1 text-sm",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),e.status==="connected"&&e.botUsername?c.jsxs("span",{className:"text-green-600 dark:text-green-400",children:["Connected as @",e.botUsername]}):e.configured?c.jsx("span",{className:"text-amber-600 dark:text-amber-400",children:"Not connected"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]}),e.error&&c.jsx("p",{className:"text-destructive text-xs",children:e.error}),e.configured&&!e.botUsername&&!e.error&&c.jsx("p",{className:"text-muted-foreground text-xs",children:"Click Save or Reconnect to start the bot. Use “Anyone” under Who can DM if you want to receive messages."})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("input",{type:"checkbox",id:"telegram-enabled",checked:y,onChange:Y=>g(Y.target.checked),className:"h-4 w-4 rounded border-input"}),c.jsx("label",{htmlFor:"telegram-enabled",className:"text-sm font-medium",children:"Enable Telegram channel"})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-token",className:"text-sm font-medium",children:"Bot token"}),c.jsx(Et,{id:"telegram-token",type:"password",placeholder:e?.configured?"(already set)":"123456789:ABC…",value:v,onChange:Y=>b(Y.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a token from @BotFather in Telegram. Leave blank to keep the current token."})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-dm-policy",className:"text-sm font-medium",children:"Who can DM the bot"}),c.jsxs("select",{id:"telegram-dm-policy",value:k,onChange:Y=>j(Y.target.value),className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"open",children:"Anyone"}),c.jsx("option",{value:"allowlist",children:"Only allowlist (set IDs below)"}),c.jsx("option",{value:"disabled",children:"Disabled"})]}),k==="disabled"&&c.jsx("p",{className:"text-muted-foreground text-xs",children:"Bot can still connect; it won’t reply to any DMs. Choose Anyone to chat from Telegram."})]}),k==="allowlist"&&c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-allow-from",className:"text-sm font-medium",children:"Allowed user IDs (comma-separated)"}),c.jsx(Et,{id:"telegram-allow-from",value:E,onChange:Y=>C(Y.target.value),placeholder:"123456789, 987654321",className:"font-mono text-sm"})]}),c.jsxs("div",{className:"space-y-2 border-t pt-4",children:[c.jsx("label",{className:"text-sm font-medium",children:"AI for Telegram"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Provider and model used when you chat via Telegram. Leave empty to use a connected provider (OpenRouter or OpenAI if configured, otherwise app default)."}),c.jsxs("div",{className:"grid gap-2 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx("label",{htmlFor:"telegram-provider",className:"text-xs text-muted-foreground",children:"Provider"}),c.jsxs("select",{id:"telegram-provider",value:M,onChange:Y=>{O(Y.target.value),D("")},className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"",children:"Use app default"}),(a?.aiProviders??[]).map(Y=>c.jsx("option",{value:Y.id,children:Y.label},Y.id))]})]}),c.jsxs("div",{className:"space-y-1",children:[c.jsx("label",{htmlFor:"telegram-model",className:"text-xs text-muted-foreground",children:"Model"}),M==="ollama"||M==="openrouter"?c.jsxs("select",{id:"telegram-model",value:T,onChange:Y=>D(Y.target.value),disabled:B,className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"",children:"Use provider default"}),R.map(Y=>c.jsx("option",{value:Y.id,children:Y.name},Y.id))]}):c.jsx(Et,{id:"telegram-model",value:T,onChange:Y=>D(Y.target.value),placeholder:M?"e.g. gpt-4o-mini":"Set provider first",disabled:!M,className:"h-9 text-sm"})]})]}),M==="ollama"&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support in Telegram, use a cloud provider."})})]}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsxs("div",{className:"flex flex-wrap gap-2",children:[c.jsxs(me,{onClick:q,disabled:d,children:[c.jsx(CO,{className:"size-4"}),d?"Saving…":"Save"]}),e?.configured&&e.status!=="connected"&&c.jsx(me,{variant:"outline",onClick:q,disabled:d,title:"Restart the bot with current settings",children:"Reconnect"})]})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Discord"}),c.jsx(kt,{children:"Let the agent post to your Discord servers. Create an app at the Discord Developer Portal, add a bot, invite it to your server with Send Messages, then paste the bot token below."})]}),c.jsxs(ct,{className:"space-y-4",children:[U&&c.jsx("div",{className:"space-y-1 text-sm",children:c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),U.configured?c.jsx("span",{className:"text-green-600 dark:text-green-400",children:"Configured"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]})}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"discord-token",className:"text-sm font-medium",children:"Bot token"}),c.jsx(Et,{id:"discord-token",type:"password",placeholder:U?.configured?"(already set)":"Paste your bot token…",value:W,onChange:Y=>ce(Y.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a token from the Discord Developer Portal (Bot section). Leave blank to keep the current token."})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:[c.jsxs("a",{href:YP,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:["Open Discord Developer Portal",c.jsx(QS,{className:"size-3"})]})," ","→ create app, add bot, then OAuth2 → URL Generator (scope: bot, permissions: Send Messages) to invite the bot to your server."]}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsx(me,{onClick:Q,disabled:le,children:le?"Saving…":"Save"})]})]})]})}const KP="https://dashboard.stripe.com/apikeys";function XP(){const[e,r]=S.useState(null),[a,l]=S.useState(""),[s,u]=S.useState(!1),[d,f]=S.useState(!0),[h,p]=S.useState(null),y=async()=>{f(!0),p(null);try{const v=await mw();r(v)}catch(v){p(v instanceof Error?v.message:String(v))}finally{f(!1)}};S.useEffect(()=>{y()},[]);const g=async()=>{u(!0),p(null);try{const v=await pw({secretKey:a.trim()||null});r(v),l("")}catch(v){p(v instanceof Error?v.message:String(v))}finally{u(!1)}};return d?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading payment settings…"})})}):c.jsx("div",{className:"space-y-4",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Stripe"}),c.jsx(kt,{children:"Let the agent list customers and invoices, and create invoices. Paste your Stripe Secret Key (from Dashboard → API keys). Use test key (sk_test_…) for development."})]}),c.jsxs(ct,{className:"space-y-4",children:[e&&c.jsx("div",{className:"space-y-1 text-sm",children:c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),e.configured?c.jsx("span",{className:"text-green-600 dark:text-green-400",children:"Configured"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]})}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"stripe-secret-key",className:"text-sm font-medium",children:"Secret key"}),c.jsx(Et,{id:"stripe-secret-key",type:"password",placeholder:e?.configured?"(already set)":"sk_test_… or sk_live_…",value:a,onChange:v=>l(v.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a key from Stripe Dashboard → Developers → API keys. Leave blank to keep the current key."})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:c.jsxs("a",{href:KP,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:["Open Stripe API keys",c.jsx(QS,{className:"size-3"})]})}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsx(me,{onClick:g,disabled:s,children:s?"Saving…":"Save"})]})]})})}function QP(){const[e,r]=S.useState(null),[a,l]=S.useState("session"),[s,u]=S.useState(""),[d,f]=S.useState([]),[h,p]=S.useState(!0),[y,g]=S.useState(!1),[v,b]=S.useState(null);S.useEffect(()=>{b(null),Qw().then(C=>{r(C),C.session.length>0?(l("session"),u(C.session[0])):C.shared.length>0&&(l("shared"),u(C.shared[0]))}).catch(C=>b(C instanceof Error?C.message:String(C))).finally(()=>p(!1))},[]);const k=a==="session"?e?.session??[]:e?.shared??[];S.useEffect(()=>{if(!s||!k.includes(s)){f([]);return}g(!0),Zw({scope:a,scope_key:s,limit:200}).then(C=>f(C.entries??[])).catch(C=>b(C instanceof Error?C.message:String(C))).finally(()=>g(!1))},[a,s]);const j=()=>{const C=new Blob([JSON.stringify({scope:a,scope_key:s,exported_at:new Date().toISOString(),entries:d},null,2)],{type:"application/json"}),M=document.createElement("a");M.href=URL.createObjectURL(C),M.download=`sulala-memory-${a}-${s.replace(/[^a-z0-9-_]/gi,"_")}.json`,M.click(),URL.revokeObjectURL(M.href)},E=C=>new Date(C).toLocaleString();return h?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading memory…"})})}):c.jsx("div",{className:"space-y-4",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsxs(wt,{className:"flex items-center gap-2 text-base",children:[c.jsx(VS,{className:"size-4"}),"Agent memory"]}),c.jsx(kt,{children:"View stored memory (session-scoped or shared across sessions). Use the chat to add entries via the write_memory tool."})]}),c.jsxs(ct,{className:"space-y-4",children:[v&&c.jsx("p",{className:"text-destructive text-sm",role:"alert",children:v}),c.jsxs("div",{className:"flex flex-wrap items-end gap-4",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"memory-scope",children:"Scope"}),c.jsxs("select",{id:"memory-scope",className:"flex h-9 w-[140px] rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",value:a,onChange:C=>{const M=C.target.value;l(M);const O=M==="session"?e?.session??[]:e?.shared??[];u(O[0]??"")},children:[c.jsx("option",{value:"session",children:"Session"}),c.jsx("option",{value:"shared",children:"Shared"})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"memory-scope-key",children:a==="session"?"Session":"Shared key"}),c.jsx("select",{id:"memory-scope-key",className:"flex h-9 min-w-[200px] max-w-[320px] rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",value:s,onChange:C=>u(C.target.value),children:k.length===0?c.jsx("option",{value:"",children:"— No keys —"}):k.map(C=>c.jsx("option",{value:C,children:C.length>40?C.slice(0,37)+"…":C},C))})]}),d.length>0&&c.jsxs(me,{variant:"outline",size:"sm",onClick:j,children:[c.jsx(wR,{className:"size-4 mr-1"}),"Export JSON"]})]}),y&&c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading entries…"}),!y&&s&&k.includes(s)&&c.jsx("div",{className:"rounded-md border",children:d.length===0?c.jsxs("p",{className:"p-4 text-muted-foreground text-sm",children:["No memory entries for this ",a," key."]}):c.jsx("ul",{className:"divide-y divide-border max-h-[400px] overflow-y-auto",children:d.map(C=>c.jsxs("li",{className:"p-3 text-sm",children:[c.jsx("p",{className:"text-foreground",children:C.content}),c.jsx("p",{className:"mt-1 text-muted-foreground text-xs",children:E(C.created_at)})]},C.id))})})]})]})})}const xh="https://portal.sulala.ai/api/gateway";function ZP({required:e=!1,portalGatewayUrl:r,onSaved:a,onError:l,portalOAuthConnectAvailable:s=!1,onOAuthConnect:u}){const[d,f]=S.useState({}),[h,p]=S.useState(r?.trim()||xh),[y,g]=S.useState(""),[v,b]=S.useState(!1),[k,j]=S.useState(!1),[E,C]=S.useState(!1);S.useEffect(()=>{p(r?.trim()||xh)},[r]),S.useEffect(()=>{b(!0),sr().then(({keys:P})=>{f(P??{})}).catch(()=>f({})).finally(()=>b(!1))},[]);const M=async()=>{const P=h.trim();if(!P){l?.("Enter Portal gateway URL");return}if(e&&!y.trim()){l?.("Enter Portal API key");return}j(!0);try{const B={PORTAL_GATEWAY_URL:P};y.trim()&&(B.PORTAL_API_KEY=y.trim()),await bs(B);const{keys:$}=await sr();f($??{}),y.trim()&&g(""),a?.()}catch(B){l?.(B instanceof Error?B.message:"Failed to save")}finally{j(!1)}},O=d.PORTAL_API_KEY==="set"?"(already set)":"sk_live_...",T=k||!h.trim()||e&&!y.trim(),D=s&&u,R=async()=>{C(!0),l?.("");try{await u?.()}catch(P){l?.(P.message)}finally{C(!1)}};return c.jsxs("div",{className:"border-border bg-muted/30 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:e?"Portal API key required":"Portal settings"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:e?"Create an API key at your Portal and enter it below. Takes effect immediately.":"Connect GitHub, Gmail, and other apps via Portal. Saved keys take effect immediately."}),v?c.jsx("p",{className:"text-muted-foreground text-xs",children:"Loading…"}):c.jsxs("div",{className:"flex flex-col gap-3",children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"portal-gateway-url",className:"text-xs",children:"Portal gateway URL"}),c.jsx(Et,{id:"portal-gateway-url",type:"url",placeholder:xh,value:h,onChange:P=>p(P.target.value),className:"h-8 font-mono text-xs"}),c.jsx("p",{className:"text-muted-foreground text-[10px]",children:"e.g. http://localhost:3004/api/gateway for local Portal, or https://portal.sulala.ai/api/gateway"})]}),D&&c.jsxs(c.Fragment,{children:[c.jsx(me,{variant:"default",size:"sm",onClick:R,disabled:E,className:"w-fit",children:E?"Opening…":"Connect with Sulala (OAuth)"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Opens in a new tab. After signing in you’ll be redirected back; refresh this page if the key doesn’t appear."}),c.jsx("p",{className:"text-muted-foreground text-xs font-medium",children:"or"})]}),c.jsxs("form",{className:"space-y-3",onSubmit:P=>{P.preventDefault(),M()},children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"portal-api-key",className:"text-xs",children:"Portal API Key"}),c.jsx(Et,{id:"portal-api-key",type:"password",placeholder:O,value:y,onChange:P=>g(P.target.value),autoComplete:"off",className:"h-8"})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsx(me,{type:"submit",variant:"secondary",size:"sm",disabled:T,children:k?"Saving…":"Save"}),c.jsx("a",{href:(()=>{const P=h.trim();if(!P)return"https://portal.sulala.ai/api/keys";try{const B=P.replace(/\/api\/gateway$/i,""),$=/^https?:\/\//i.test(B)?B:`https://${B}`;return new URL("/api-keys",$).toString()}catch{return"https://portal.sulala.ai/api/keys"}})(),target:"_blank",rel:"noreferrer",className:"text-primary hover:underline text-xs",children:"Create API key →"})]})]})]})]})}function JP({storeBaseUrl:e,onSaved:r,onError:a}){const[l,s]=S.useState({}),[u,d]=S.useState(""),[f,h]=S.useState(!1),[p,y]=S.useState(!1);S.useEffect(()=>{h(!0),sr().then(({keys:k})=>s(k??{})).catch(()=>s({})).finally(()=>h(!1))},[]);const g=async()=>{y(!0);try{const k={};u.trim()&&(k.STORE_PUBLISH_API_KEY=u.trim()),await bs(k);const{keys:j}=await sr();s(j??{}),u.trim()&&d(""),r?.()}catch(k){a?.(k instanceof Error?k.message:"Failed to save")}finally{y(!1)}},v=l.STORE_PUBLISH_API_KEY==="set"?"(already set)":"sk_pub_...",b=e?`${e.replace(/\/$/,"")}/my-skills`:null;return c.jsxs("div",{className:"border-border bg-muted/30 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Store publish API key"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Publish skills from the dashboard (Skills → My skills → Publish to store). Create a key on the store (My skills → Create publish API key), then paste it here."}),f?c.jsx("p",{className:"text-muted-foreground text-xs",children:"Loading…"}):c.jsxs("form",{className:"flex flex-col gap-3",onSubmit:k=>{k.preventDefault(),g()},children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"store-publish-api-key",className:"text-xs",children:"API key"}),c.jsx(Et,{id:"store-publish-api-key",type:"password",placeholder:v,value:u,onChange:k=>d(k.target.value),autoComplete:"off",className:"h-8"})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsx(me,{type:"submit",variant:"secondary",size:"sm",disabled:p,children:p?"Saving…":"Save"}),b&&c.jsx("a",{href:b,target:"_blank",rel:"noreferrer",className:"text-primary hover:underline text-xs",children:"Create API key on store →"})]})]})]})}const WP=[{value:"overview",label:"Overview",icon:KR},{value:"tasks",label:"Tasks",icon:nO},{value:"logs",label:"Logs",icon:jm},{value:"files",label:"File states",icon:IR},{value:"ai-providers",label:"AI Providers",icon:XS},{value:"channels",label:"Channels",icon:ns},{value:"payment",label:"Payment",icon:bR},{value:"memory",label:"Memory",icon:VS},{value:"portal",label:"Portal",icon:eO},{value:"config",label:"Watched folders",icon:nw}];function eU(e){return c.jsx("div",{className:"flex flex-1 flex-col min-h-0",children:c.jsx(au,{defaultValue:"overview",orientation:"vertical",className:"flex flex-1 flex-col min-h-0",children:c.jsxs("div",{className:"flex flex-1 min-h-0",children:[c.jsx(lu,{variant:"line",className:"w-52 shrink-0 flex flex-col h-auto rounded-none p-2 gap-0.5",children:WP.map(({value:r,label:a,icon:l})=>c.jsxs(pa,{value:r,className:Se("w-full justify-start gap-2 rounded-md px-3 py-2 h-auto font-normal","data-[state=active]:bg-background data-[state=active]:shadow-sm data-[state=active]:font-medium"),children:[c.jsx(l,{className:"size-4 shrink-0"}),c.jsx("span",{className:"truncate",children:a})]},r))}),c.jsxs("div",{className:"flex-1 min-w-0 overflow-auto p-4",children:[c.jsx(Vt,{value:"overview",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(T4,{health:e.health,loading:e.loading,connected:e.connected,events:e.events})}),c.jsx(Vt,{value:"tasks",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(qP,{tasks:e.tasks,loading:e.loading,load:e.load,enqueueType:e.enqueueType,setEnqueueType:e.setEnqueueType,enqueuePayload:e.enqueuePayload,setEnqueuePayload:e.setEnqueuePayload,enqueueing:e.enqueueing,actionTaskId:e.actionTaskId,handleTaskCancel:e.handleTaskCancel,handleTaskRetry:e.handleTaskRetry,handleEnqueue:e.handleEnqueue})}),c.jsx(Vt,{value:"logs",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(GP,{logs:e.logs,load:e.load})}),c.jsx(Vt,{value:"files",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx($P,{fileStates:e.fileStates,load:e.load})}),c.jsx(Vt,{value:"ai-providers",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(FP,{})}),c.jsx(Vt,{value:"channels",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(VP,{})}),c.jsx(Vt,{value:"payment",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(XP,{})}),c.jsx(Vt,{value:"memory",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(QP,{})}),c.jsx(Vt,{value:"portal",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(tU,{config:e.config,onError:e.onError})}),c.jsx(Vt,{value:"config",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(BP,{config:e.config})})]})]})})})}function tU({config:e,onError:r}){const a=e?.portalGatewayUrl??null,l=e?.portalOAuthConnectAvailable===!0,s=async()=>{const{url:d}=await Nm();window.open(d,"_blank","noopener,noreferrer")},u=Jl();return c.jsxs("div",{className:"flex flex-col gap-4",children:[c.jsx(ZP,{portalGatewayUrl:a,onError:r,portalOAuthConnectAvailable:l,onOAuthConnect:l?s:void 0}),c.jsx(JP,{storeBaseUrl:u,onError:r})]})}const nU=100;function rU(e){const[r,a]=S.useState([]),[l,s]=S.useState(!1),u=S.useRef(null),d=S.useRef(e?.onSkillsChanged);return d.current=e?.onSkillsChanged,S.useEffect(()=>{const f=Cw(),h=new WebSocket(f);return h.onopen=()=>s(!0),h.onclose=()=>s(!1),h.onmessage=p=>{try{const y=JSON.parse(p.data);a(g=>[y,...g].slice(0,nU)),y.type==="skills_changed"&&d.current&&d.current()}catch{}},h.onerror=()=>{},u.current=h,()=>{h.close(),u.current=null,s(!1)}},[]),{events:r,connected:l}}function aU({className:e,checked:r,onCheckedChange:a,onChange:l,...s}){const u=r===!0;return c.jsx("input",{type:"checkbox",checked:u,onChange:d=>{l?.(d),a?.(d.target.checked)},"data-slot":"checkbox",className:Se("border-input size-4 shrink-0 rounded border transition-colors","focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-2","accent-primary disabled:opacity-50",e),...s})}const lU="modulepreload",iU=function(e){return"/"+e},Kb={},sU=function(r,a,l){let s=Promise.resolve();if(a&&a.length>0){let p=function(y){return Promise.all(y.map(g=>Promise.resolve(g).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};var d=p;document.getElementsByTagName("link");const f=document.querySelector("meta[property=csp-nonce]"),h=f?.nonce||f?.getAttribute("nonce");s=p(a.map(y=>{if(y=iU(y),y in Kb)return;Kb[y]=!0;const g=y.endsWith(".css"),v=g?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${y}"]${v}`))return;const b=document.createElement("link");if(b.rel=g?"stylesheet":lU,g||(b.as="script"),b.crossOrigin="",b.href=y,h&&b.setAttribute("nonce",h),document.head.appendChild(b),g)return new Promise((k,j)=>{b.addEventListener("load",k),b.addEventListener("error",()=>j(new Error(`Unable to preload CSS for ${y}`)))})}))}function u(f){const h=new Event("vite:preloadError",{cancelable:!0});if(h.payload=f,window.dispatchEvent(h),!h.defaultPrevented)throw f}return s.then(f=>{for(const h of f||[])h.status==="rejected"&&u(h.reason);return r().catch(u)})},uj=[{id:"openrouter",label:"OpenRouter",envKey:"OPENROUTER_API_KEY",apiKeyUrl:"https://openrouter.ai/keys"},{id:"ollama",label:"Ollama (Local – No API Key Required)",envKey:null,apiKeyUrl:null},{id:"openai",label:"OpenAI",envKey:"OPENAI_API_KEY",apiKeyUrl:"https://platform.openai.com/api-keys"},{id:"anthropic",label:"Anthropic (Claude)",envKey:"ANTHROPIC_API_KEY",apiKeyUrl:"https://console.anthropic.com/settings/keys"},{id:"google",label:"Google / Gemini",envKey:"GOOGLE_GEMINI_API_KEY",apiKeyUrl:"https://aistudio.google.com/app/apikey"}],oU={openai:"OPENAI_API_KEY",anthropic:"ANTHROPIC_API_KEY",google:"GOOGLE_GEMINI_API_KEY",gemini:"GEMINI_API_KEY",openrouter:"OPENROUTER_API_KEY"};function cU(e){const[r,a]=S.useState({statusLoading:!0,statusComplete:null,step:0,selectedProviders:[],envKeys:{},envKeysInput:{},recommendedModels:[],registrySkills:[],selectedSkills:[],ollamaRunning:null,ollamaStatusLoading:!1,pullState:{inProgress:!1,model:"",lastLine:"",percent:0},pullingModels:new Set,loading:!1,error:null,systemCapabilities:null}),l=S.useCallback(async()=>{a(T=>({...T,statusLoading:!0}));try{const{complete:T}=await Cm();return a(D=>({...D,statusComplete:T,statusLoading:!1})),T}catch(T){return a(D=>({...D,statusComplete:!1,statusLoading:!1,error:T instanceof Error?T.message:"Failed to load status"})),!1}},[]),s=S.useCallback(async()=>{try{const{keys:T}=await sr();return a(D=>({...D,envKeys:T})),T}catch{return{}}},[]),u=S.useCallback(async()=>{try{const{models:T}=await yw();return a(D=>({...D,recommendedModels:T})),T}catch{return[]}},[]),d=S.useCallback(async()=>{try{const{skills:T}=await wc();return a(D=>({...D,registrySkills:T})),T}catch{return[]}},[]),f=S.useCallback(async()=>{a(T=>({...T,ollamaStatusLoading:!0}));try{const{running:T}=await Kl();return a(D=>({...D,ollamaRunning:T,ollamaStatusLoading:!1})),T}catch{return a(T=>({...T,ollamaRunning:!1,ollamaStatusLoading:!1})),!1}},[]),h=S.useCallback(async()=>{const{fetchOllamaPullStatus:T}=await sU(async()=>{const{fetchOllamaPullStatus:R}=await Promise.resolve().then(()=>j4);return{fetchOllamaPullStatus:R}},void 0),D=await T();return a(R=>({...R,pullState:D})),D},[]);S.useEffect(()=>{l()},[l]);const p=S.useCallback(async()=>{try{const T=await Uw();return a(D=>({...D,systemCapabilities:T})),T}catch{return a(T=>({...T,systemCapabilities:null})),null}},[]);return S.useEffect(()=>{r.step===0&&p()},[r.step,p]),S.useEffect(()=>{(r.step===1||r.step===2)&&s()},[r.step,s]),S.useEffect(()=>{r.step===2&&r.selectedProviders.includes("ollama")&&(u(),f())},[r.step,r.selectedProviders,u,f]),S.useEffect(()=>{r.step===4&&d()},[r.step,d]),S.useEffect(()=>{if(!r.pullState.inProgress)return;const T=setInterval(h,500);return()=>clearInterval(T)},[r.pullState.inProgress,h]),{...r,loadStatus:l,loadSystemCapabilities:p,installOllama:async()=>{a(T=>({...T,error:null}));try{await Iw(),await f()}catch(T){a(D=>({...D,error:T instanceof Error?T.message:"Failed to install Ollama"}))}},loadEnv:s,loadRecommendedModels:u,loadRegistrySkills:d,checkOllama:f,setStep:T=>a(D=>({...D,step:T})),setSelectedProviders:T=>a(D=>({...D,selectedProviders:T})),setEnvKeysInput:T=>a(D=>({...D,envKeysInput:T})),setSelectedSkills:T=>a(D=>({...D,selectedSkills:T})),setError:T=>a(D=>({...D,error:T})),saveEnv:async(T,D)=>{a(R=>({...R,loading:!0,error:null}));try{const R=r.envKeysInput,P={...D};for(const[$,U]of Object.entries(R))typeof U=="string"&&U.trim()&&(P[$]=U.trim());await bs(P);const{keys:B}=await sr();a($=>({...$,envKeys:B,envKeysInput:{},loading:!1,step:T??2}))}catch(R){a(P=>({...P,loading:!1,error:R instanceof Error?R.message:"Failed to save API keys"}))}},pullModel:async T=>{a(D=>({...D,pullingModels:new Set(D.pullingModels).add(T),error:null}));try{await vw(T),h()}catch(D){a(R=>({...R,pullingModels:(()=>{const P=new Set(R.pullingModels);return P.delete(T),P})(),error:D instanceof Error?D.message:"Failed to pull model"}))}},installSkill:async T=>{a(D=>({...D,loading:!0,error:null}));try{await Tm(T,"managed"),a(D=>({...D,selectedSkills:[...new Set([...D.selectedSkills,T])],loading:!1}))}catch(D){a(R=>({...R,loading:!1,error:D instanceof Error?D.message:"Failed to install skill"}))}},finishOnboarding:async()=>{a(T=>({...T,loading:!0,error:null}));try{await xw(),a(T=>({...T,statusComplete:!0,loading:!1})),e?.()}catch(T){a(D=>({...D,loading:!1,error:T instanceof Error?T.message:"Failed to complete onboarding"}))}}}}function uU(e){if(!e)return null;const r=e.match(/~?(\d+(?:\.\d+)?)\s*(GB|MB|gb|mb)/);if(!r)return null;const a=parseFloat(r[1]),l=r[2].toUpperCase();return l==="GB"?Math.round(a*1024*1024*1024):l==="MB"?Math.round(a*1024*1024):null}const dj=S.createContext(null);function Es(){const e=S.useContext(dj);if(!e)throw new Error("OnboardingFlow must wrap steps");return e}const dU=["Choose AI Provider","Provider Configuration","Integrations","Ollama Model Setup","Finish"],fU=["Choose AI Provider","Provider Configuration","Integrations","Finish"];function hU(){const{selectedProviders:e,setSelectedProviders:r,setStep:a,systemCapabilities:l}=Es(),s=l&&!l.ollamaSuitable,u=f=>{if(f==="ollama"&&s)return;const h=e.includes(f)?e.filter(p=>p!==f):[...e,f];r(h)},d=e.length>=1;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("p",{className:"text-muted-foreground text-sm",children:"Select at least one AI provider to continue. Ollama runs locally and needs no API key."}),s&&l&&c.jsxs("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:[c.jsxs("p",{className:"text-amber-700 dark:text-amber-400",children:["⚠️ ",l.ollamaSuitableReason]}),c.jsx("p",{className:"text-muted-foreground mt-1 text-xs",children:"Use a cloud provider (OpenAI, OpenRouter, etc.) instead."})]}),e.includes("ollama")&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support and best results, add a cloud provider."})}),c.jsx("div",{className:"grid gap-3",children:uj.map(f=>c.jsxs("label",{className:`border-input flex items-center gap-3 rounded-lg border p-4 transition-colors ${f.id==="ollama"&&s?"cursor-not-allowed opacity-60":"hover:bg-muted/50 cursor-pointer"}`,children:[c.jsx(aU,{checked:e.includes(f.id),onCheckedChange:()=>u(f.id),disabled:f.id==="ollama"&&!!s}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"font-medium",children:f.label}),f.id==="ollama"&&s&&c.jsx("div",{className:"text-amber-600 dark:text-amber-400 mt-0.5 text-xs",children:"Not available on this system"}),f.envKey&&c.jsxs("div",{className:"text-muted-foreground mt-0.5 flex flex-wrap items-center gap-x-2 text-xs",children:[c.jsx("span",{children:"Requires API key"}),"apiKeyUrl"in f&&typeof f.apiKeyUrl=="string"&&c.jsx("a",{href:f.apiKeyUrl,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:"Get API key →"})]})]})]},f.id))}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx("div",{}),c.jsxs(me,{disabled:!d,onClick:()=>a(1),children:["Next",c.jsx(zr,{className:"ml-1 size-4"})]})]})]})}function mU(){const{selectedProviders:e,envKeys:r,envKeysInput:a,setEnvKeysInput:l,saveEnv:s,setStep:u,loading:d,error:f}=Es(),h=e.filter(j=>j!=="ollama"),p={OPENAI_API_KEY:"OpenAI API Key",ANTHROPIC_API_KEY:"Anthropic API Key",GOOGLE_GEMINI_API_KEY:"Google Gemini API Key",GEMINI_API_KEY:"Gemini API Key (alt)",OPENROUTER_API_KEY:"OpenRouter API Key"},y={};uj.forEach(j=>{j.envKey&&"apiKeyUrl"in j&&typeof j.apiKeyUrl=="string"&&(y[j.envKey]=j.apiKeyUrl)});const g=h.flatMap(j=>{const E=oU[j];return E?[E]:[]}),b=!g.some(j=>r[j]!=="set")||g.length===0,k=g.some(j=>(a[j]??"").trim().length>0);return c.jsxs("div",{className:"space-y-6",children:[h.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No cloud providers selected. Skipping API keys."}):c.jsxs(c.Fragment,{children:[c.jsxs("p",{className:"text-muted-foreground text-sm",children:["Enter API keys for selected providers. Keys are saved securely to ",c.jsx("code",{className:"rounded bg-muted px-1 text-xs",children:"~/.sulala/.env"}),"."]}),c.jsx("div",{className:"grid gap-4",children:g.map(j=>c.jsxs("div",{className:"space-y-2",children:[c.jsxs("div",{className:"flex flex-wrap items-center gap-x-2",children:[c.jsx(Xt,{htmlFor:j,children:p[j]??j}),y[j]&&c.jsx("a",{href:y[j],target:"_blank",rel:"noopener noreferrer",className:"text-primary text-xs hover:underline",children:"Get API key →"})]}),c.jsx(Et,{id:j,type:"password",placeholder:r[j]==="set"?"(already set)":"sk-...",value:a[j]??"",onChange:E=>l({...a,[j]:E.target.value}),autoComplete:"off"})]},j))})]}),f&&c.jsx("div",{className:"text-destructive text-sm",children:f}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>u(0),children:"Back"}),c.jsxs("div",{className:"flex gap-2",children:[(b||k)&&c.jsx(me,{variant:"outline",onClick:()=>u(2),children:h.length===0?"Next":"Skip for now"}),k&&c.jsx(me,{onClick:()=>s(2),disabled:d,children:d?"Saving…":"Save & Next"}),b&&!k&&h.length>0&&c.jsx(me,{onClick:()=>u(2),children:"Next"})]})]})]})}function pU(){const{setStep:e,selectedProviders:r}=Es(),l=r.includes("ollama")?4:3;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("p",{className:"text-muted-foreground text-sm",children:"You can connect apps (GitHub, Gmail, Twitter, etc.) in two ways:"}),c.jsxs("ul",{className:"text-muted-foreground list-disc list-inside space-y-1 text-sm",children:[c.jsxs("li",{children:[c.jsx("strong",{children:"MCP Servers"})," — Integrations → MCP Servers tab. Add servers and API keys (e.g. YouTube, Twitter). Find more at"," ",c.jsx("a",{href:"https://mcpservers.org/",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline hover:no-underline",children:"mcpservers.org"}),"."]}),c.jsxs("li",{children:[c.jsx("strong",{children:"Sulala Portal"})," — To use Portal for OAuth apps, add your API key later in ",c.jsx("strong",{children:"Settings → Portal"}),"."]})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Neither is required now. You can set up either option anytime from the dashboard."}),c.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[c.jsx(me,{variant:"outline",onClick:()=>e(1),children:"Back"}),c.jsxs(me,{onClick:()=>e(l),children:["Next",c.jsx(zr,{className:"ml-1 size-4"})]})]})]})}function gU({m:e,installed:r,pulling:a,onPull:l}){return c.jsxs("div",{className:"border-input flex flex-col gap-2 rounded-lg border p-4 sm:flex-row sm:items-center sm:justify-between",children:[c.jsxs("div",{children:[c.jsx("div",{className:"font-medium",children:e.name}),c.jsx("div",{className:"text-muted-foreground text-sm",children:e.description}),c.jsxs("div",{className:"mt-1 flex flex-wrap gap-2 text-xs",children:[c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(ZS,{className:"size-3"})," ",e.size]}),c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(YO,{className:"size-3"})," ",e.ram," RAM"]}),c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(XS,{className:"size-3"})," ",e.cpu]}),e.gpu!=="None"&&c.jsxs("span",{children:["GPU: ",e.gpu]})]})]}),c.jsx(me,{variant:r?"secondary":"default",size:"sm",onClick:l,disabled:r||a,children:r?"Installed":a?"Installing…":"Install"})]})}function xU(){const{recommendedModels:e,ollamaRunning:r,ollamaStatusLoading:a,pullState:l,pullingModels:s,pullModel:u,installOllama:d,setStep:f,checkOllama:h,systemCapabilities:p,error:y}=Es(),g=()=>{window.confirm("Ollama will be downloaded and installed (~500MB). This requires network access and sufficient disk space. Continue?")&&d()},v=j=>{const E=p?.storageFreeBytes??0,C=uU(j.size);if(C!=null&&E>0&&C>E){alert(`Insufficient storage. This model needs ~${j.size}. You have ${(E/1024/1024/1024).toFixed(1)}GB free.`);return}window.confirm(`Download and install ${j.name}? This will use ~${j.size} of disk space. Continue?`)&&u(j.id)},b=new Set;l.inProgress&&l.model&&b.add(l.model);const k=p&&!p.ollamaSuitable;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support and best results, use a cloud provider."})}),k&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsxs("p",{className:"text-amber-700 dark:text-amber-400",children:["⚠️ ",p.ollamaSuitableReason," Ollama may not run well here."]})}),a?c.jsx("p",{className:"text-muted-foreground text-sm",children:"Checking Ollama…"}):r===!1?c.jsxs("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-4",children:[c.jsxs("p",{className:"text-amber-700 dark:text-amber-400 text-sm",children:["⚠️ Ollama is not running. Click Install to download Ollama, or install from"," ",c.jsx("a",{href:"https://ollama.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"ollama.com"})," ","and run ",c.jsx("code",{children:"ollama serve"}),"."]}),c.jsxs("div",{className:"mt-2 flex gap-2",children:[c.jsx(me,{variant:"default",size:"sm",onClick:g,disabled:a,children:"Install Ollama"}),c.jsx(me,{variant:"outline",size:"sm",onClick:h,disabled:a,children:"Check again"})]})]}):null,l.inProgress&&c.jsxs("div",{className:"rounded-lg border border-blue-500/50 bg-blue-500/10 p-4",children:[c.jsxs("div",{className:"font-medium",children:["Pulling ",l.model,"…"]}),l.percent>=0&&l.percent<=100&&c.jsx(Om,{value:l.percent,className:"mt-2 h-2"}),l.lastLine&&c.jsx("div",{className:"text-muted-foreground mt-1 truncate font-mono text-xs",children:l.lastLine})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Select models to install. You can skip and install later from Settings."}),c.jsx("div",{className:"grid gap-3",children:e.map(j=>c.jsx(gU,{m:j,installed:!1,pulling:s.has(j.id),onPull:()=>v(j)},j.id))}),y&&c.jsx("div",{className:"text-destructive text-sm",children:y}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>f(2),children:"Back"}),c.jsx(me,{onClick:()=>f(4),children:"Skip or Next"})]})]})}function Xb(){const{selectedProviders:e,finishOnboarding:r,loading:a,error:l,setStep:s}=Es(),u=e.includes("ollama");return c.jsxs("div",{className:"space-y-6",children:[c.jsxs("div",{children:[c.jsx("h3",{className:"font-semibold",children:"Summary"}),c.jsx("ul",{className:"text-muted-foreground mt-2 space-y-1 text-sm",children:c.jsxs("li",{className:"flex items-center gap-2",children:[c.jsx(KS,{className:"size-4 text-green-600"}),"AI providers: ",e.join(", ")||"None"]})})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Click Finish to complete onboarding and open the dashboard. You can change providers anytime in Settings."}),l&&c.jsx("div",{className:"text-destructive text-sm",children:l}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>s(u?3:2),children:"Back"}),c.jsx(me,{onClick:r,disabled:a,children:a?"Finishing…":"Finish"})]})]})}function yU({onComplete:e}){const r=cU(e),{step:a,selectedProviders:l}=r,s=l.includes("ollama"),u=s?5:4,d=s?dU:fU,f=Math.max(0,Math.min(a,u-1)),h={0:"Choose which AI providers you want to use.",1:"Enter API keys for cloud providers.",2:"Connect apps via MCP servers or Sulala Portal (optional). Add Portal API key in Settings → Portal if you use Portal.",...s?{3:"Install local models with Ollama.",4:"Review and complete setup."}:{3:"Review and complete setup."}};return c.jsx(dj.Provider,{value:r,children:c.jsx("div",{className:"bg-background flex min-h-screen flex-col items-center justify-center p-4",children:c.jsxs("div",{className:"w-full max-w-2xl space-y-8",children:[c.jsxs("div",{className:"text-center",children:[c.jsx("h1",{className:"text-2xl font-bold",children:"Welcome to Sulala"}),c.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["Step ",f+1," of ",u,": ",d[f]]}),c.jsx(Om,{value:(f+1)/u*100,className:"mt-4 h-2"})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:d[f]}),c.jsx(kt,{children:h[f]})]}),c.jsxs(ct,{children:[f===0&&c.jsx(hU,{}),f===1&&c.jsx(mU,{}),f===2&&c.jsx(pU,{}),f===3&&(s?c.jsx(xU,{}):c.jsx(Xb,{})),f===4&&s&&c.jsx(Xb,{})]})]})]})})})}function vU(){const[e,r]=S.useState(null),[a,l]=S.useState(()=>{if(typeof window>"u")return"chat";const C=new URLSearchParams(window.location.search).get("page");return["chat","skills","integrations","jobs","settings","overview","tasks","logs","files","config"].includes(C)?C:"chat"}),[s,u]=S.useState(null);S.useEffect(()=>{console.log("fetching onboarding status"),Cm().then(({complete:C})=>{console.log("onboarding status",C),r(C)}).catch(C=>{console.error("error fetching onboarding status",C);const M=C.message||String(C);r(!!(M.includes("429")||M.includes("fetch")))})},[]);const[d,f]=S.useState(null),h=C4(C=>u(C)),p=_4(C=>u(C)),y=J4(a,C=>u(C),{onMissingIntegrations:C=>f(C)}),g=RP(a,C=>u(C)),v=HP(a);S.useEffect(()=>{(a==="settings"||a==="jobs")&&h.load()},[a]);const b=S.useRef(()=>{});b.current=p.loadSkills;const{events:k,connected:j}=rU({onSkillsChanged:()=>b.current?.()});if(S.useEffect(()=>{a==="skills"&&p.loadSkillsData()},[a]),e===null)return c.jsx("div",{className:"bg-background flex min-h-screen flex-col items-center justify-center",children:c.jsx("div",{className:"text-muted-foreground text-sm",children:"Loading…"})});if(!e)return c.jsx(bU,{onComplete:()=>r(!0)});const E=C=>{if(l(C),typeof window<"u"){const M=new URL(window.location.href);M.searchParams.set("page",C),window.history.replaceState({},"",M.toString())}};return c.jsxs(w4,{activePage:a,onNavigate:E,error:s,children:[a==="chat"&&c.jsx(MP,{...y,integrations:g.integrations,onNavigateToIntegrations:()=>E("integrations"),missingIntegrationsFromServer:d,onClearMissingIntegrationsFromServer:()=>f(null)}),a==="skills"&&c.jsx(q4,{...p}),a==="integrations"&&c.jsx(zP,{...g,onError:C=>u(C)}),a==="jobs"&&c.jsx(IP,{schedules:h.schedules,loading:h.loading,load:h.load,onCreateSchedule:h.handleCreateSchedule,onUpdateSchedule:h.handleUpdateSchedule,onDeleteSchedule:h.handleDeleteSchedule,onRunSchedule:h.handleRunSchedule,onFetchScheduleRuns:h.handleFetchScheduleRuns}),a==="settings"&&c.jsx(eU,{health:h.health,loading:h.loading,connected:j,events:k,tasks:h.tasks,load:h.load,enqueueType:h.enqueueType,setEnqueueType:h.setEnqueueType,enqueuePayload:h.enqueuePayload,setEnqueuePayload:h.setEnqueuePayload,enqueueing:h.enqueueing,actionTaskId:h.actionTaskId,handleTaskCancel:h.handleTaskCancel,handleTaskRetry:h.handleTaskRetry,handleEnqueue:h.handleEnqueue,logs:h.logs,fileStates:h.fileStates,config:v,onError:C=>u(C)})]})}function bU({onComplete:e}){return c.jsx(yU,{onComplete:e})}zC.createRoot(document.getElementById("root")).render(c.jsx(S.StrictMode,{children:c.jsx(vU,{})}));
83
+ `)):""}function _P({message:e,isLast:r,isStreaming:a}){const l=e,s=l.created_at?ek(l.created_at):null,u=l.usage,d=u&&((u.prompt_tokens??0)>0||(u.completion_tokens??0)>0);if(l.role==="user"){const f=TP(l.content);return c.jsxs("div",{className:"flex items-start gap-2 justify-end",children:[c.jsxs("div",{className:"border-border bg-muted/30 flex max-w-[min(85%,42rem)] flex-col gap-0.5 rounded-lg rounded-tr-sm px-3 py-2 text-sm",children:[c.jsx("div",{className:"chat-markdown text-foreground break-words [&>*:last-child]:mb-0",children:c.jsx(zb,{remarkPlugins:[qb],components:Gb,children:f})}),s&&c.jsx("div",{className:"text-muted-foreground text-right text-xs",children:s})]}),c.jsx(W4,{className:"size-8 shrink-0",children:c.jsx(eD,{className:"rounded-full",children:c.jsx(PO,{className:"size-4"})})})]})}if(l.role==="assistant")return c.jsxs("div",{className:"flex items-start gap-2",children:[c.jsxs("div",{className:"size-8 shrink-0 flex items-center justify-center overflow-hidden rounded-full bg-muted",children:[c.jsx("img",{src:"/icon.svg",alt:"",className:"size-5 dark:hidden","aria-hidden":!0}),c.jsx("img",{src:"/logo_white.svg",alt:"",className:"size-5 hidden dark:block","aria-hidden":!0})]}),c.jsxs("div",{className:"border-border bg-muted/30 flex max-w-[min(85%,42rem)] flex-1 flex-col gap-0.5 rounded-lg rounded-tl-sm px-3 py-2 text-sm",children:[(l.thinking??"")&&c.jsxs("details",{className:"text-muted-foreground border-border mb-2 rounded border border-dashed py-1.5 pl-2 pr-2 text-xs",open:a,children:[c.jsxs("summary",{className:"cursor-pointer font-medium flex items-center gap-2",children:["Thinking",a&&c.jsx(zh,{className:"ml-1"})]}),c.jsx("pre",{className:"mt-1.5 whitespace-pre-wrap break-words font-sans",children:l.thinking})]}),l.content??""?c.jsxs("div",{className:"flex items-end gap-x-1",children:[c.jsx("div",{className:"chat-markdown text-foreground min-w-0 flex-1 [&>*:last-child]:mb-0",children:c.jsx(zb,{remarkPlugins:[qb],components:Gb,children:String(l.content)})}),a&&c.jsx(tD,{className:"shrink-0"})]}):a&&r?c.jsx(zh,{}):null,l.tool_calls?.length?c.jsxs("details",{className:"text-muted-foreground mt-1 text-xs group/details",children:[c.jsxs("summary",{className:"cursor-pointer list-none flex items-center gap-1 opacity-80 hover:opacity-100 [&::-webkit-details-marker]:hidden",children:[c.jsx(zr,{className:"size-3.5 shrink-0 transition-transform group-open/details:rotate-90"}),c.jsx("span",{children:"Show details"}),c.jsxs("span",{className:"opacity-75",children:["(",l.tool_calls.length," tool call",l.tool_calls.length!==1?"s":"",")"]})]}),c.jsx("div",{className:"mt-1.5 border-l border-border/50 pl-4",children:c.jsxs("div",{className:"opacity-80",children:["Tool calls:"," ",l.tool_calls.map(f=>`${f.name}(${f.arguments?.slice(0,40)??""}${(f.arguments?.length??0)>40?"…":""})`).join(", ")]})})]}):null,s||d||l.cost_usd!=null&&l.cost_usd>0?c.jsxs("div",{className:"text-muted-foreground mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs opacity-80",children:[s&&c.jsx("span",{children:s}),d&&c.jsxs("span",{children:[u.prompt_tokens??0," in / ",u.completion_tokens??0," out",u.total_tokens!=null&&` (${u.total_tokens} total)`]}),l.cost_usd!=null&&l.cost_usd>0&&c.jsxs("span",{title:"Estimated cost for this response",children:["$",l.cost_usd.toFixed(6)]})]}):null]})]});if(l.role==="tool"||l.name){const f=l.name??"tool",h=String(l.content??"");return c.jsxs("details",{className:"text-muted-foreground group/tool flex gap-2 pl-10 text-xs",children:[c.jsxs("summary",{className:"cursor-pointer list-none flex flex-1 items-start gap-2 [&::-webkit-details-marker]:hidden",children:[c.jsx(zr,{className:"size-3.5 shrink-0 mt-0.5 transition-transform group-open/tool:rotate-90"}),c.jsxs("div",{className:"flex-1 min-w-0 rounded bg-muted/20 px-2 py-1",children:[c.jsxs("span",{className:"font-medium",children:["Tool result (",f,")"]}),s&&c.jsxs("span",{className:"ml-1 opacity-75",children:["· ",s]})]})]}),c.jsx("div",{className:"pl-10 pr-2 pb-1",children:c.jsx("pre",{className:"mt-1 whitespace-pre-wrap break-words rounded bg-muted/20 p-2 text-xs font-sans",children:h||"(empty)"})})]})}return null}function MP(e){const{configuredProviders:r=[],chatMessages:a,chatInput:l,setChatInput:s,chatProvider:u,setChatProvider:d,chatModel:f,setChatModel:h,chatModelsLoading:p,chatSessions:y,chatSessionsLoading:g,chatLoading:v,chatAgentSessionId:b,models:k,ollamaRunning:j,ollamaStatusLoading:E,ollamaPullState:C,checkOllama:M,handleSelectSession:O,handleChatSend:T,handleNewChat:D,pendingActionId:R,pendingActionDetails:P,pendingActionLoading:B,handleApprovePending:$,handleRejectPending:U,setLastAppliedIdea:ne,chatAttachments:W=[],setChatAttachments:ce,integrations:le=[],onNavigateToIntegrations:F,missingIntegrationsFromServer:z=null,onClearMissingIntegrationsFromServer:q}=e,[Q,Y]=S.useState(!1),[A,L]=S.useState([]),[Z,_]=S.useState(""),[ue,he]=S.useState(!1),fe=jP(le),pe=a.length===0&&l.length===0,De=se=>{s(se.base_prompt),ne?.(se)},Ee=se=>{L(se.required_integrations),_(se.title),Y(!0)},ge=se=>{Y(!1),F?.()},Me=se=>{O(se),he(!1)},ee=b&&y.length>0?y.find(se=>se.id===b)?.session_key??"Current chat":"Chat history",Re=se=>{se.required_integrations.filter(mt=>!fe.includes(mt)).length===0?De(se):Ee(se)},Be=u==="ollama"&&j===!1&&!E,ln=u==="ollama"&&C?.inProgress,Zn=u==="ollama";return c.jsxs(ot,{className:"flex flex-1 flex-col",children:[c.jsxs(St,{className:"flex flex-row items-center justify-between space-y-0",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"AI Chat"}),c.jsx(kt,{children:"Agent with sessions and tools (e.g. run_task). OpenAI supports tool calls."})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsxs(_m,{children:[c.jsx(Mm,{asChild:!0,children:c.jsxs(me,{variant:"outline",size:"sm",className:"gap-1.5",children:[c.jsx(JR,{className:"size-3.5"}),"Try an idea"]})}),c.jsx(Rm,{align:"end",className:"min-w-[220px]",children:sj.map(se=>c.jsxs(ha,{onClick:()=>Re(se),className:"flex flex-col items-start gap-0.5 py-2",children:[c.jsx("span",{className:"font-medium",children:se.title}),c.jsx("span",{className:"text-muted-foreground text-xs font-normal",children:se.description})]},se.id))})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:D,children:"New chat"})]})]}),c.jsxs(ct,{className:"flex flex-1 flex-col gap-4",children:[Be&&c.jsxs("div",{className:"bg-muted border-border flex flex-wrap items-center justify-between gap-2 rounded-lg border p-3 text-sm",children:[c.jsx("span",{children:"Ollama is not running. Set it up to use the default AI."}),c.jsxs("div",{className:"flex gap-2",children:[c.jsx(me,{variant:"outline",size:"sm",asChild:!0,children:c.jsx("a",{href:"/onboard",target:"_blank",rel:"noopener noreferrer",children:"Set up Ollama"})}),c.jsx(me,{variant:"secondary",size:"sm",onClick:M,disabled:E,children:"Check again"})]})]}),ln&&C&&c.jsxs("div",{className:"bg-primary/10 border-primary/20 flex flex-col gap-2 rounded-lg border p-3 text-sm",children:[c.jsxs("div",{className:"font-medium",children:["Pulling model ",C.model,"…"]}),C.percent>=0&&C.percent<=100&&c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("div",{className:"bg-muted h-2 flex-1 overflow-hidden rounded-full",children:c.jsx("div",{className:"bg-primary h-full transition-[width] duration-300",style:{width:`${C.percent}%`}})}),c.jsxs("span",{className:"text-muted-foreground shrink-0 text-xs",children:[C.percent,"%"]})]}),C.lastLine&&c.jsx("div",{className:"text-muted-foreground truncate font-mono text-xs",title:C.lastLine,children:C.lastLine})]}),Zn&&c.jsxs("div",{className:"bg-amber-500/10 border-amber-500/50 flex items-center gap-2 rounded-lg border p-3 text-sm",children:[c.jsx(Xv,{className:"size-4 shrink-0 text-amber-600 dark:text-amber-400","aria-hidden":!0}),c.jsx("span",{className:"text-amber-700 dark:text-amber-400",children:"Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support, switch to a cloud provider."})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsxs(Jc,{open:ue,onOpenChange:he,children:[c.jsxs(me,{variant:"outline",size:"sm",className:"gap-1.5 min-w-[140px] justify-between",onClick:()=>he(!0),disabled:g,children:[c.jsx(GR,{className:"size-3.5 shrink-0"}),c.jsx("span",{className:"truncate",children:ee})]}),c.jsxs(Wc,{side:"right",className:"flex flex-col w-full sm:max-w-md",children:[c.jsxs(eu,{children:[c.jsx(tu,{children:"Chat history"}),c.jsx(nu,{children:"Switch to a previous chat or start a new one."})]}),c.jsxs("div",{className:"flex-1 overflow-y-auto px-4 pb-4",children:[c.jsx(me,{variant:"outline",size:"sm",className:"w-full justify-start mb-2",onClick:()=>Me(""),children:"New chat"}),y.length===0&&!g&&c.jsx("p",{className:"text-muted-foreground text-sm py-2",children:"No chats yet."}),g&&c.jsxs("p",{className:"text-muted-foreground text-sm py-2 flex items-center gap-2",children:[c.jsx(vc,{className:"size-4 animate-spin"}),"Loading…"]}),c.jsx("ul",{className:"space-y-1",children:y.map(se=>c.jsx("li",{children:c.jsx("button",{type:"button",onClick:()=>Me(se.id),className:Se("w-full text-left rounded-md px-3 py-2 text-sm transition-colors",se.id===b?"bg-primary/10 text-primary font-medium":"hover:bg-muted"),children:c.jsx("span",{className:"truncate block",children:se.session_key})})},se.id))})]})]})]}),c.jsxs("select",{className:"border-input bg-background h-9 rounded-md border px-3 text-sm",value:u,onChange:se=>{const ze=se.target.value;d(ze);const mt=r.find(He=>He.id===ze);h(mt?.defaultModel||"")},children:[(r.length===0||!u||!r.some(se=>se.id===u))&&c.jsx("option",{value:"",children:r.length===0?"No provider configured":"Select provider"}),r.map(se=>c.jsx("option",{value:se.id,children:se.label},se.id))]}),c.jsxs("select",{className:"border-input bg-background min-w-[200px] rounded-md border px-3 py-2 text-sm",value:f,onChange:se=>h(se.target.value),disabled:(u==="openrouter"||u==="ollama")&&p,children:[(u==="openrouter"||u==="ollama")&&p?c.jsx("option",{value:f,children:"Loading models…"}):k.map(se=>c.jsx("option",{value:se.id,children:se.name},se.id)),(u==="openrouter"||u==="ollama")&&!p&&k.length===0&&f&&c.jsx("option",{value:f,children:f})]})]}),c.jsx(Wl,{className:"min-h-[240px] flex-1 rounded-md border p-3",children:c.jsxs("div",{className:"space-y-3",children:[a.length===0&&c.jsx("p",{className:"text-muted-foreground text-sm",children:"Send a message to start. Provider and model can be changed above."}),a.map((se,ze)=>c.jsx(_P,{message:se,isLast:ze===a.length-1,isStreaming:v&&ze===a.length-1},ze)),R&&c.jsxs(ot,{className:"border-amber-500/50 bg-amber-500/5",children:[c.jsxs(St,{className:"pb-2",children:[c.jsxs(wt,{className:"flex items-center gap-2 text-base",children:[c.jsx(Xv,{className:"size-4 text-amber-600"}),"Approve this action"]}),c.jsx(kt,{children:"The agent wants to run a tool that can change files or run commands. Approve to continue or reject to cancel."})]}),c.jsx(ct,{className:"space-y-3",children:B&&!P?c.jsxs("div",{className:"text-muted-foreground flex items-center gap-2 py-2",children:[c.jsx(vc,{className:"size-4 animate-spin"}),"Loading…"]}):c.jsxs(c.Fragment,{children:[P&&c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"font-mono text-sm font-medium",children:P.toolName}),Object.keys(P.args).length>0&&c.jsx("pre",{className:"bg-muted max-h-32 overflow-auto rounded p-2 text-xs",children:JSON.stringify(P.args,null,2)})]}),c.jsxs("div",{className:"flex gap-2",children:[c.jsxs(me,{size:"sm",onClick:$,children:[c.jsx(KS,{className:"size-4"}),"Approve"]}),c.jsxs(me,{size:"sm",variant:"destructive",onClick:U,children:[c.jsx(Sc,{className:"size-4"}),"Reject"]})]})]})})]}),v&&a.length>0&&a[a.length-1]?.role==="user"&&c.jsxs("div",{className:"flex items-start gap-2",children:[c.jsxs("div",{className:"size-8 shrink-0 flex items-center justify-center overflow-hidden rounded-full bg-muted",children:[c.jsx("img",{src:"/icon.svg",alt:"",className:"size-5 dark:hidden","aria-hidden":!0}),c.jsx("img",{src:"/logo_white.svg",alt:"",className:"size-5 hidden dark:block","aria-hidden":!0})]}),c.jsx("div",{className:"border-border bg-muted/30 flex items-center gap-2 rounded-lg rounded-tl-sm px-3 py-2 text-sm",children:c.jsx(zh,{})})]})]})}),pe&&c.jsx(CP,{connectedIds:fe,onSelectIdea:De,onMissingIntegrations:Ee}),W.length>0&&c.jsx("div",{className:"border-border flex flex-wrap gap-2 rounded-md border p-2",children:W.map((se,ze)=>c.jsxs("div",{className:"relative",children:[se.type.startsWith("image/")?c.jsx("img",{src:URL.createObjectURL(se),alt:se.name,className:"h-14 w-14 rounded object-cover"}):c.jsx("div",{className:"border-input flex h-14 w-14 items-center justify-center rounded border text-xs",children:se.name.slice(0,8)}),c.jsx("button",{type:"button",className:"absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-muted-foreground text-muted hover:bg-foreground hover:text-background",onClick:()=>ce(mt=>mt.filter((He,Ut)=>Ut!==ze)),"aria-label":"Remove attachment",children:c.jsx(Sc,{className:"h-3 w-3"})})]},`${se.name}-${ze}`))}),c.jsxs("div",{className:"flex gap-2 items-end",children:[c.jsxs("label",{className:"cursor-pointer shrink-0 rounded-md border border-input px-2 py-2 text-muted-foreground hover:bg-muted/50",children:[c.jsx("input",{type:"file",accept:"image/*,video/*,.mp4,.webm,.mov,.m4v,.avi",className:"sr-only",multiple:!0,onChange:se=>{const ze=se.target.files?Array.from(se.target.files):[];ce(mt=>[...mt,...ze]),se.target.value=""}}),c.jsx(YR,{className:"h-5 w-5","aria-hidden":!0})]}),c.jsx("textarea",{className:"border-input bg-background field-sizing-content min-h-10 max-h-48 w-full min-w-0 flex-1 resize-none rounded-md border px-3 py-2 text-sm leading-relaxed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",placeholder:"Type a message…",value:l,onChange:se=>s(se.target.value),onKeyDown:se=>{se.key==="Enter"&&!se.shiftKey&&(se.preventDefault(),T())},rows:1}),c.jsx(me,{onClick:T,disabled:v||!l.trim()&&W.length===0,children:v?"Sending…":"Send"})]}),c.jsx(AP,{open:Q||z!=null&&z.length>0,onOpenChange:se=>{se||(Y(!1),q?.())},requiredIntegrations:Q?A:z??[],connectedIds:fe,ideaTitle:Q?Z:"",onConnect:ge})]})]})}function RP(e,r){const[a,l]=S.useState([]),[s,u]=S.useState(!1),[d,f]=S.useState(null),[h,p]=S.useState(!1),[y,g]=S.useState(null),[v,b]=S.useState(void 0),[k,j]=S.useState(!1),[E,C]=S.useState(!1),M=15e3,O=S.useCallback(async()=>{u(!0),p(!1),g(null),b(void 0),j(!1),C(!1);const B=new Promise(($,U)=>{setTimeout(()=>U(new Error("Request timed out. Check that the agent and integrations service are running.")),M)});try{const $=await Promise.race([Ka(),B]),U=!!($.portalGatewayUrl?.trim()&&$.integrationsMode!=="portal");if(j(U),C($.portalOAuthConnectAvailable===!0),$.integrationsMode==="portal"){p(!0),g($.portalGatewayUrl??null);const W=$.integrationsUrl?.trim()||void 0;try{let ce;if(W)try{const{integrations:z}=await Promise.race([Ah(W),B]);ce=z.map(q=>({...q,connections:[]}))}catch{ce=rc().map(q=>({id:q.id,name:q.name,iconUrl:q.logoUrl??"",description:q.description,connections:[]}))}else ce=rc().map(q=>({id:q.id,name:q.name,iconUrl:q.logoUrl??"",description:q.description,connections:[]}));const le=new Map(ce.map(z=>[z.id,z])),{connections:F}=await Promise.race([Ow(),B]);for(const z of F){const q=z.provider||"other";let Q=le.get(q);if(!Q){const Y=q.charAt(0).toUpperCase()+q.slice(1);Q={id:q,name:Y,iconUrl:"",description:"Connected via Portal",connections:[]},le.set(q,Q),ce.push(Q)}Q.connections.push(z)}l(ce)}catch{l(rc().map(ce=>({id:ce.id,name:ce.name,iconUrl:ce.logoUrl??"",description:ce.description,connections:[],tokenOnly:ce.tokenOnly})))}u(!1);return}const ne=$.integrationsUrl?.trim()||void 0;if(b(ne),ne){const{integrations:W}=await Promise.race([Ah(ne),B]);l(W)}else l(rc().map(W=>({id:W.id,name:W.name,iconUrl:W.logoUrl??"",description:W.description,connections:[],tokenOnly:W.tokenOnly})))}catch($){r($.message),l([])}finally{u(!1)}},[r]),T=S.useRef(O);T.current=O,S.useEffect(()=>{(e==="integrations"||e==="chat")&&T.current()},[e]);const D=S.useCallback(async B=>{f(B);try{const $=typeof window<"u"?`${window.location.origin}${window.location.pathname}?page=integrations`:"";if(h){const{authUrl:U}=await Dw(B,$);window.location.href=U}else{const{authUrl:U}=await Tw(B,$,v);window.location.href=U}}catch($){r($.message),f(null)}},[h,v,r]),R=S.useCallback(async B=>{try{h?await zw(B):await _w(B,v),await O()}catch($){r($.message)}},[h,v,O,r]),P=S.useCallback(async B=>{try{const{url:$}=await Nm(B);window.open($,"_blank","noopener,noreferrer")}catch($){r($.message)}},[r]);return{integrations:a,loading:s,connectingProvider:d,integrationsManagedByPortal:h,portalGatewayUrl:y,portalUrlSetButKeyMissing:k,portalOAuthConnectAvailable:E,load:O,handleConnect:D,handleDisconnect:R,startOAuthConnect:P}}function $b(e){try{const r=JSON.parse(e),a=Array.isArray(r)?r:r&&typeof r=="object"&&"servers"in r&&Array.isArray(r.servers)?r.servers:null;if(!a)return null;const l=[];for(const s of a){const u=s&&typeof s=="object"?s:{},d=typeof u.name=="string"?u.name.trim():"",f=typeof u.command=="string"?u.command.trim():"";if(!d||!f)continue;const h=Array.isArray(u.args)?u.args.map(y=>String(y)):void 0;let p;if(u.env&&typeof u.env=="object"&&!Array.isArray(u.env)){p={};for(const[y,g]of Object.entries(u.env))typeof y=="string"&&typeof g=="string"&&(p[y]=g);Object.keys(p).length===0&&(p=void 0)}l.push({name:d,command:f,args:h,env:p})}return l}catch{return null}}function OP({onError:e}){const[r,a]=S.useState([]),[l,s]=S.useState(!0),[u,d]=S.useState(!1),[f,h]=S.useState(null),[p,y]=S.useState("form"),[g,v]=S.useState(""),b=async()=>{s(!0),h(null);try{const D=(await Mw()).servers??[];return a(D),{servers:D}}catch(T){return h(T instanceof Error?T.message:String(T)),e?.(T instanceof Error?T.message:String(T)),{servers:[]}}finally{s(!1)}};S.useEffect(()=>{b()},[]),S.useEffect(()=>{p==="json"&&v(JSON.stringify({servers:r},null,2))},[p,r]);const k=async()=>{d(!0),h(null);try{let T;if(p==="json"){const R=$b(g);if(!R){h('Invalid JSON. Use { "servers": [ { "name", "command", "args"?, "env"? } ] } or an array of servers.'),d(!1);return}T=R.map(P=>({...P,env:P.env?Object.fromEntries(Object.entries(P.env).map(([B,$])=>[B,$===""?"***":$])):void 0}))}else T=r.map(R=>({...R,env:R.env?Object.fromEntries(Object.entries(R.env).map(([P,B])=>[P,B===""?"***":B])):void 0}));await Rw(T);const{servers:D}=await b();p==="json"&&v(JSON.stringify({servers:D},null,2))}catch(T){h(T instanceof Error?T.message:String(T)),e?.(T instanceof Error?T.message:String(T))}finally{d(!1)}},j=()=>{const T=$b(g);T?.length&&a(T),y("form")},E=()=>{a(T=>[...T,{name:"",command:"npx",args:["-y","package-name"],env:{}}])},C=(T,D)=>{a(R=>{const P=[...R];return P[T]={...P[T],...D},P})},M=(T,D,R)=>{a(P=>{const B=[...P],$={...B[T].env??{}};return R===""?delete $[D]:$[D]=R,B[T]={...B[T],env:$},B})},O=T=>{a(D=>D.filter((R,P)=>P!==T))};return l?c.jsx("div",{className:"text-muted-foreground text-sm",children:"Loading MCP servers…"}):c.jsx("div",{className:"flex flex-col gap-4 max-w-2xl",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsxs(wt,{className:"flex items-center gap-2",children:[c.jsx(tw,{className:"size-5"}),"MCP Servers"]}),c.jsxs(kt,{className:"space-y-1",children:[c.jsxs("span",{className:"block",children:["Add MCP servers as an alternative to Integrations (e.g. YouTube, Twitter, Gmail with API keys). Use the form or paste JSON. Tools appear as ",c.jsx("code",{className:"rounded bg-muted px-1",children:"mcp_<name>_<tool>"}),". Config is saved to ",c.jsx("code",{className:"rounded bg-muted px-1",children:"~/.sulala/mcp.json"}),"."]}),c.jsxs("span",{className:"block",children:["Find more servers at"," ",c.jsx("a",{href:"https://mcpservers.org/",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline hover:no-underline",children:"mcpservers.org"}),"."]})]})]}),c.jsxs(ct,{className:"flex flex-col gap-4",children:[c.jsxs(au,{value:p,onValueChange:T=>{T==="form"?j():y("json")},className:"w-full",children:[c.jsxs(lu,{className:"grid w-full max-w-xs grid-cols-2",children:[c.jsx(pa,{value:"form",className:"flex items-center gap-2",children:"Form"}),c.jsxs(pa,{value:"json",className:"flex items-center gap-2",children:[c.jsx(zR,{className:"size-4"}),"JSON"]})]}),c.jsxs(Vt,{value:"json",className:"mt-4 space-y-2",children:[c.jsxs(Xt,{className:"text-muted-foreground text-sm",children:["Paste or edit config. Use ",c.jsx("code",{className:"rounded bg-muted px-1",children:'{ "servers": [ ... ] }'})," or an array of server objects."]}),c.jsx("textarea",{className:"border-input bg-background min-h-[280px] w-full rounded-md border px-3 py-2 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-ring",value:g,onChange:T=>v(T.target.value),spellCheck:!1})]}),c.jsxs(Vt,{value:"form",className:"mt-4",children:[f&&c.jsx("p",{className:"text-destructive text-sm",children:f}),r.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No MCP servers configured. Click Add server and set name, command, args, and any env keys (e.g. YOUTUBE_API_KEY)."}):c.jsx("div",{className:"flex flex-col gap-4",children:r.map((T,D)=>c.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsxs("span",{className:"font-medium text-sm",children:["Server ",D+1]}),c.jsx(me,{type:"button",variant:"ghost",size:"sm",onClick:()=>O(D),className:"text-muted-foreground hover:text-destructive",children:c.jsx(bc,{className:"size-4"})})]}),c.jsxs("div",{className:"grid gap-2 grid-cols-[auto_1fr] items-center text-sm",children:[c.jsx(Xt,{className:"text-muted-foreground",children:"Name"}),c.jsx(Et,{placeholder:"e.g. youtube",value:T.name,onChange:R=>C(D,{name:R.target.value.trim()})}),c.jsx(Xt,{className:"text-muted-foreground",children:"Command"}),c.jsx(Et,{placeholder:"e.g. npx",value:T.command,onChange:R=>C(D,{command:R.target.value.trim()})}),c.jsx(Xt,{className:"text-muted-foreground",children:"Args"}),c.jsx(Et,{placeholder:"e.g. -y, zubeid-youtube-mcp-server (comma-separated)",value:Array.isArray(T.args)?T.args.join(", "):"",onChange:R=>C(D,{args:R.target.value.split(",").map(P=>P.trim()).filter(Boolean)})})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{className:"text-muted-foreground text-sm",children:"Env (API keys, etc.)"}),c.jsxs("div",{className:"space-y-2",children:[Object.entries(T.env??{}).map(([R,P])=>c.jsxs("div",{className:"flex gap-2 items-center",children:[c.jsx(Et,{className:"flex-1 font-mono text-sm",placeholder:"KEY",value:R,readOnly:!0}),c.jsx(Et,{type:"password",className:"flex-1 font-mono text-sm",placeholder:"value",value:P==="***"?"":P,onChange:B=>M(D,R,B.target.value)}),c.jsx(me,{type:"button",variant:"ghost",size:"sm",onClick:()=>M(D,R,""),children:c.jsx(bc,{className:"size-4"})})]},R)),c.jsx(DP,{onAdd:(R,P)=>{R&&M(D,R,P)}})]})]})]},D))}),c.jsxs("div",{className:"flex gap-2",children:[c.jsxs(me,{type:"button",variant:"outline",size:"sm",onClick:E,children:[c.jsx(WS,{className:"size-4 mr-1"}),"Add server"]}),c.jsx(me,{type:"button",size:"sm",onClick:k,disabled:u,children:u?"Saving…":"Save & reload tools"})]})]})]}),p==="json"&&c.jsx("div",{className:"flex gap-2 pt-2",children:c.jsx(me,{type:"button",size:"sm",onClick:k,disabled:u,children:u?"Saving…":"Save & reload tools"})})]})]})})}function DP({onAdd:e}){const[r,a]=S.useState(""),[l,s]=S.useState(""),u=()=>{const d=r.trim();d&&(e(d,l.trim()),a(""),s(""))};return c.jsxs("div",{className:"flex gap-2 items-center",children:[c.jsx(Et,{className:"flex-1 font-mono text-sm",placeholder:"e.g. YOUTUBE_API_KEY",value:r,onChange:d=>a(d.target.value)}),c.jsx(Et,{type:"password",className:"flex-1 font-mono text-sm",placeholder:"value",value:l,onChange:d=>s(d.target.value)}),c.jsx(me,{type:"button",variant:"outline",size:"sm",onClick:u,children:"Add env"})]})}function zP({integrations:e,loading:r,connectingProvider:a,integrationsManagedByPortal:l,portalUrlSetButKeyMissing:s=!1,load:u,handleConnect:d,handleDisconnect:f,onError:h}){const[p,y]=S.useState("");S.useEffect(()=>{const b=new URLSearchParams(window.location.search),k=b.get("connectionId"),j=b.get("error"),E=b.get("oauth"),C=b.get("message");if(k||j){if(j&&h)try{h(decodeURIComponent(j))}catch{h("OAuth failed")}u();const M=new URL(window.location.href);M.searchParams.delete("connectionId"),M.searchParams.delete("error"),window.history.replaceState({},"",M.toString())}else if(E==="success"||E==="error"){E==="error"&&C&&h&&h(C==="exchange_failed"?"Token exchange failed. Check PORTAL_OAUTH_CLIENT_SECRET and redirect_uri.":C==="no_token"?"No access token in response.":C),u();const M=new URL(window.location.href);M.searchParams.delete("oauth"),M.searchParams.delete("message"),window.history.replaceState({},"",M.toString())}},[u,h]);const g=S.useMemo(()=>{const b=p.trim().toLowerCase();return b?e.filter(k=>k.name.toLowerCase().includes(b)||k.description.toLowerCase().includes(b)||k.id.toLowerCase().includes(b)):e},[e,p]),v=r&&e.length===0?c.jsxs("div",{className:"text-muted-foreground flex flex-1 items-center justify-center gap-2 py-12",children:[c.jsx(vc,{className:"size-5 animate-spin"}),c.jsx("span",{children:"Loading…"})]}):l?c.jsxs("div",{className:"flex flex-1 flex-col gap-6",children:[c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("h1",{className:"text-2xl font-semibold tracking-tight",children:"Apps"}),c.jsx(bt,{variant:"secondary",className:"rounded-full text-[10px] font-medium uppercase",children:"Beta"})]}),c.jsxs("p",{className:"text-muted-foreground text-sm",children:["Connect and disconnect apps here. Your agent uses ",c.jsx("code",{className:"rounded bg-muted px-1",children:"PORTAL_API_KEY"})," or OAuth to access them."]})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure Portal gateway and connect in ",c.jsx("strong",{children:"Settings → Portal"}),"."]}),e.length>0&&c.jsx("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-end",children:c.jsxs("div",{className:"relative w-full sm:w-64",children:[c.jsx(Kv,{className:"text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2"}),c.jsx(Et,{type:"search",placeholder:"Search apps",value:p,onChange:b=>y(b.target.value),className:"pl-9"})]})}),g.length>0?c.jsx("div",{className:"grid gap-2 sm:grid-cols-2",children:g.map(b=>c.jsx(Yb,{app:b,connecting:a===b.id,onConnect:()=>d(b.id),onDisconnect:f},b.id))}):p.trim()?c.jsx("p",{className:"text-muted-foreground py-8 text-center text-sm",children:"No apps match your search."}):c.jsx("p",{className:"text-muted-foreground py-4 text-center text-sm",children:"No connections yet. Click an app to connect."})]}):e.length===0&&!r?s?c.jsxs("div",{className:"flex flex-1 flex-col gap-4 p-4",children:[c.jsxs("div",{className:"border-amber-500/50 bg-amber-500/10 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Portal API key required"}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure Portal gateway URL and API key (or connect with OAuth) in ",c.jsx("strong",{children:"Settings → Portal"}),"."]})]}),c.jsx(me,{variant:"secondary",size:"sm",onClick:()=>u(),className:"self-start",children:"Retry"})]}):c.jsx("div",{className:"flex flex-1 flex-col gap-4 p-4",children:c.jsxs("div",{className:"border-destructive/50 bg-destructive/5 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Could not reach the integrations service"}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Configure ",c.jsx("strong",{children:"Settings → Portal"})," (recommended), or set ",c.jsx("code",{className:"rounded bg-muted px-1",children:"INTEGRATIONS_URL"})," in the agent .env and run the integrations service."]}),c.jsx(me,{variant:"secondary",size:"sm",onClick:()=>u(),children:"Retry"})]})}):c.jsxs("div",{className:"flex flex-1 flex-col gap-6 p-4",children:[c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("h1",{className:"text-2xl font-semibold tracking-tight",children:"Apps"}),c.jsx(bt,{variant:"secondary",className:"rounded-full text-[10px] font-medium uppercase",children:"Beta"})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Connect your favorite apps. The agent uses these via connectionId — no secrets in skills."})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:["Portal gateway and Connect with Sulala are in ",c.jsx("strong",{children:"Settings → Portal"}),"."]}),c.jsx("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-end",children:c.jsxs("div",{className:"relative w-full sm:w-64",children:[c.jsx(Kv,{className:"text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2"}),c.jsx(Et,{type:"search",placeholder:"Search apps",value:p,onChange:b=>y(b.target.value),className:"pl-9"})]})}),c.jsx("div",{className:"grid gap-2 sm:grid-cols-2",children:g.map(b=>c.jsx(Yb,{app:b,connecting:a===b.id,onConnect:()=>d(b.id),onDisconnect:f},b.id))}),g.length===0&&c.jsx("p",{className:"text-muted-foreground py-8 text-center text-sm",children:"No apps match your search."})]});return c.jsx("div",{className:"flex flex-1 flex-col p-4 min-h-0",children:c.jsxs(au,{defaultValue:"mcp",className:"flex flex-1 flex-col min-h-0",children:[c.jsxs(lu,{className:"w-full max-w-xs grid grid-cols-2 mb-4",children:[c.jsxs(pa,{value:"mcp",className:"flex items-center gap-2",children:[c.jsx(tw,{className:"size-4"}),"MCP Servers"]}),c.jsxs(pa,{value:"connections",className:"flex items-center gap-2",children:[c.jsx(JS,{className:"size-4"}),"Connections"]})]}),c.jsx(Vt,{value:"mcp",className:"mt-0 flex-1 data-[state=inactive]:hidden min-h-0",children:c.jsx(OP,{onError:h})}),c.jsx(Vt,{value:"connections",className:"mt-0 flex-1 data-[state=inactive]:hidden min-h-0",children:v})]})})}const LP="https://discord.com/developers/applications",PP="https://dashboard.stripe.com/apikeys";function Yb({app:e,connecting:r,onConnect:a,onDisconnect:l,portalMode:s=!1}){const u=e.connections.length>0,d=e.tokenOnly===!0,f=e.id==="discord",h=e.id==="stripe",p=()=>{if(!u){if(d&&f){window.open(LP,"_blank","noopener,noreferrer");return}if(d&&h){window.open(PP,"_blank","noopener,noreferrer");return}a()}};return c.jsxs("div",{className:"border-border hover:bg-muted/50 flex cursor-pointer items-center gap-3 rounded-lg border px-3 py-2.5 transition-colors",onClick:p,onKeyDown:y=>{(y.key==="Enter"||y.key===" ")&&(y.preventDefault(),p())},role:"button",tabIndex:0,children:[c.jsx("div",{className:"bg-muted flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg p-1.5",children:e.iconUrl?c.jsx("img",{src:e.iconUrl,alt:"",className:"size-full object-contain"}):c.jsx("span",{className:"text-muted-foreground text-sm font-medium",children:e.name.charAt(0)})}),c.jsxs("div",{className:"min-w-0 flex-1",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"font-medium truncate",children:e.name}),u&&c.jsx(bt,{variant:"secondary",className:"shrink-0 text-[10px]",children:"Connected"}),d&&!u&&c.jsx(bt,{variant:"outline",className:"shrink-0 text-[10px]",children:"Setup"})]}),c.jsx("p",{className:"text-muted-foreground truncate text-sm",children:e.description}),f&&d&&c.jsxs("p",{className:"text-muted-foreground mt-0.5 text-xs",children:["Set ",c.jsx("code",{className:"rounded bg-muted px-1",children:"DISCORD_BOT_TOKEN"})," in agent .env or Settings → Channels. Click to open Discord Developer Portal."]}),h&&d&&c.jsxs("p",{className:"text-muted-foreground mt-0.5 text-xs",children:["Set Secret Key in Settings → Payment or ",c.jsx("code",{className:"rounded bg-muted px-1",children:"STRIPE_SECRET_KEY"})," in agent .env. Click to open Stripe API keys."]})]}),c.jsx("div",{className:"flex shrink-0 items-center gap-1",children:u&&!s?e.connections.map(y=>c.jsx(me,{variant:"ghost",size:"icon",className:"size-8",onClick:g=>{g.stopPropagation(),l(y.id)},title:"Disconnect",children:c.jsx(bc,{className:"size-3.5 text-muted-foreground"})},y.id)):u&&s?c.jsx("span",{title:"Manage in Portal",children:c.jsx(zr,{className:"text-muted-foreground size-5"})}):r?c.jsx(vc,{className:"text-muted-foreground size-5 animate-spin"}):c.jsx(zr,{className:"text-muted-foreground size-5"})})]})}function Jm({className:e,...r}){return c.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:c.jsx("table",{"data-slot":"table",className:Se("w-full caption-bottom text-sm",e),...r})})}function Wm({className:e,...r}){return c.jsx("thead",{"data-slot":"table-header",className:Se("[&_tr]:border-b",e),...r})}function ep({className:e,...r}){return c.jsx("tbody",{"data-slot":"table-body",className:Se("[&_tr:last-child]:border-0",e),...r})}function ga({className:e,...r}){return c.jsx("tr",{"data-slot":"table-row",className:Se("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",e),...r})}function Zt({className:e,...r}){return c.jsx("th",{"data-slot":"table-head",className:Se("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...r})}function Ht({className:e,...r}){return c.jsx("td",{"data-slot":"table-cell",className:Se("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...r})}const cj=[{label:"Every day at 9:00 AM",value:"0 9 * * *"},{label:"Every day at 8:00 AM",value:"0 8 * * *"},{label:"Every day at 12:00 PM (noon)",value:"0 12 * * *"},{label:"Every day at 6:00 PM",value:"0 18 * * *"},{label:"Every hour",value:"0 * * * *"},{label:"Every 30 minutes",value:"*/30 * * * *"},{label:"Every 15 minutes",value:"*/15 * * * *"},{label:"Every Monday at 9:00 AM",value:"0 9 * * 1"},{label:"Every weekday at 9:00 AM",value:"0 9 * * 1-5"},{label:"Custom (advanced)",value:"__custom__"}];function UP(e){return cj.find(a=>a.value===e&&a.value!=="__custom__")?.label??(e?`Custom: ${e}`:"—")}function IP(e){const{schedules:r,load:a,onCreateSchedule:l,onUpdateSchedule:s,onDeleteSchedule:u,onRunSchedule:d,onFetchScheduleRuns:f}=e,[h,p]=S.useState("Morning post"),[y,g]=S.useState(""),[v,b]=S.useState("Fetch daily news and post one to Bluesky."),[k,j]=S.useState("0 9 * * *"),[E,C]=S.useState(""),[M,O]=S.useState(!0),[T,D]=S.useState(""),[R,P]=S.useState(""),[B,$]=S.useState([]),[U,ne]=S.useState([]),[W,ce]=S.useState(!1),[le,F]=S.useState(!1),[z,q]=S.useState(null),[Q,Y]=S.useState(null),[A,L]=S.useState([]),[Z,_]=S.useState(!1),[ue,he]=S.useState(null),fe=k==="__custom__"?E.trim():k;S.useEffect(()=>{Ka().then(ee=>$(ee?.aiProviders??[])).catch(()=>$([]))},[]),S.useEffect(()=>{if(!T||T!=="ollama"&&T!=="openrouter"){ne([]),P("");return}ce(!0),Ss(T).then(ee=>ne(ee.models??[])).catch(()=>ne([])).finally(()=>ce(!1))},[T]);const pe=async()=>{if(v.trim()){F(!0);try{const ee=M?[{channel:"telegram",target:"default"}]:[];await l({name:h.trim()||"Scheduled job",description:y.trim()||void 0,cron_expression:fe.trim(),prompt:v.trim(),delivery:ee.length?ee:void 0,provider:T.trim()||null,model:R.trim()||null}),p("Morning post"),g(""),b("Fetch daily news and post one to Bluesky."),j("0 9 * * *"),C(""),O(!0),D(""),P("")}finally{F(!1)}}},De=async ee=>{q(ee.id);try{await s(ee.id,{enabled:!ee.enabled})}finally{q(null)}},Ee=async ee=>{q(ee);try{await u(ee)}finally{q(null)}},ge=async ee=>{q(ee.id),he(null);try{const Re=await d(ee.id);he({jobId:ee.id,message:`Job enqueued (task ${Re.id.slice(0,12)}…)`}),a()}catch(Re){he({jobId:ee.id,message:Re instanceof Error?Re.message:"Run failed"})}finally{q(null)}},Me=ee=>{Y(ee)};return S.useEffect(()=>{if(!Q){L([]);return}_(!0),f(Q.id).then(({runs:ee})=>L(ee)).catch(()=>L([])).finally(()=>_(!1))},[Q?.id,f]),c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"New job"}),c.jsx(kt,{children:"Describe what you want in plain language. The agent will use your skills (e.g. news, Bluesky) and run on schedule. Job results are sent to Telegram: the first chat that messages the bot becomes the notification target, or set it in Settings → Channels."})]}),c.jsxs(ct,{className:"space-y-4",children:[c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Name"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:h,onChange:ee=>p(ee.target.value),placeholder:"Morning post"})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Schedule"}),c.jsx("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:k,onChange:ee=>j(ee.target.value),children:cj.map(ee=>c.jsx("option",{value:ee.value,children:ee.label},ee.value))}),k==="__custom__"&&c.jsxs("div",{className:"mt-2 space-y-1",children:[c.jsx("label",{className:"text-muted-foreground block text-xs",children:"Cron expression: minute hour day month weekday (e.g. 0 9 * * * = 9:00 daily)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 font-mono text-sm",value:E,onChange:ee=>C(ee.target.value),placeholder:"0 9 * * *"})]})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Description (optional)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:y,onChange:ee=>g(ee.target.value),placeholder:"Short context for this job"})]}),c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"AI Provider (optional)"}),c.jsxs("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:T,onChange:ee=>D(ee.target.value),children:[c.jsx("option",{value:"",children:"Use default (OpenRouter/OpenAI if configured)"}),B.map(ee=>c.jsx("option",{value:ee.id,children:ee.label},ee.id)),B.length===0&&c.jsxs(c.Fragment,{children:[c.jsx("option",{value:"",children:"Use default"}),c.jsx("option",{value:"openrouter",children:"OpenRouter"}),c.jsx("option",{value:"openai",children:"OpenAI"}),c.jsx("option",{value:"claude",children:"Claude"}),c.jsx("option",{value:"gemini",children:"Gemini"}),c.jsx("option",{value:"ollama",children:"Ollama"})]})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Leave empty to use app default (prefers OpenRouter or OpenAI when configured). Do not use Ollama for jobs unless it is always running."}),T==="ollama"&&c.jsxs("div",{className:"rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-sm text-amber-800 dark:text-amber-200",children:[c.jsx("strong",{children:"Warning:"})," Using Ollama for scheduled jobs is not recommended. The job will not run if Ollama is not running when the job triggers. Use OpenRouter or OpenAI for reliable scheduled runs."]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Model (optional)"}),T&&(T==="ollama"||T==="openrouter")?c.jsxs("select",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:R,onChange:ee=>P(ee.target.value),disabled:W,children:[c.jsx("option",{value:"",children:"Use provider default"}),U.map(ee=>c.jsx("option",{value:ee.id,children:ee.name},ee.id))]}):c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:R,onChange:ee=>P(ee.target.value),placeholder:T?B.find(ee=>ee.id===T)?.defaultModel??"e.g. gpt-4o-mini":"Select provider first",disabled:!T})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Prompt *"}),c.jsx("textarea",{className:"border-input bg-background min-h-[80px] w-full rounded-md border px-3 py-2 text-sm",value:v,onChange:ee=>b(ee.target.value),placeholder:"e.g. Fetch daily news and post one to Bluesky.",rows:3})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-4",children:[c.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[c.jsx("input",{type:"checkbox",checked:M,onChange:ee=>O(ee.target.checked)}),"Notify via Telegram when job completes or fails"]}),c.jsx(me,{onClick:pe,disabled:le||!v.trim()||!fe,children:le?"Adding…":"Add job"})]})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Scheduled jobs"}),c.jsx(kt,{children:"Agent jobs (prompt + schedule). You get a Telegram notification on success or failure if delivery is set."})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:a,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[320px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"Name"}),c.jsx(Zt,{children:"Prompt"}),c.jsx(Zt,{children:"Model"}),c.jsx(Zt,{children:"Cron"}),c.jsx(Zt,{children:"Delivery"}),c.jsx(Zt,{children:"Enabled"}),c.jsx(Zt,{children:"Created"}),c.jsx(Zt,{className:"w-[70px]",children:"Actions"})]})}),c.jsx(ep,{children:r.length===0?c.jsx(ga,{children:c.jsx(Ht,{colSpan:8,className:"text-muted-foreground text-center text-sm",children:"No scheduled jobs. Add one above."})}):r.map(ee=>c.jsxs(ga,{children:[c.jsx(Ht,{className:"font-medium",children:ee.name||ee.id}),c.jsx(Ht,{className:"max-w-[200px] truncate text-sm",children:ee.prompt||ee.task_type||"—"}),c.jsx(Ht,{className:"text-muted-foreground max-w-[120px] truncate text-xs",children:ee.provider?`${ee.provider}${ee.model?` / ${ee.model}`:""}`:"—"}),c.jsx(Ht,{className:"text-xs",children:UP(ee.cron_expression)}),c.jsx(Ht,{children:ee.delivery?c.jsx(bt,{variant:"outline",children:"Telegram"}):c.jsx("span",{className:"text-muted-foreground text-xs",children:"—"})}),c.jsx(Ht,{children:c.jsx(bt,{variant:ee.enabled?"default":"secondary",children:ee.enabled?"On":"Off"})}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(ee.created_at)}),c.jsx(Ht,{children:c.jsxs("div",{className:"flex flex-col gap-1",children:[c.jsxs(_m,{children:[c.jsx(Mm,{asChild:!0,children:c.jsx(me,{variant:"ghost",size:"sm",className:"h-8 w-8 p-0",disabled:z===ee.id,title:"Actions",children:c.jsx(ER,{className:"size-4"})})}),c.jsxs(Rm,{align:"end",children:[c.jsxs(ha,{onClick:()=>ge(ee),children:[c.jsx(pO,{className:"size-4"}),"Test"]}),c.jsxs(ha,{onClick:()=>Me(ee),children:[c.jsx(jm,{className:"size-4"}),"Logs"]}),c.jsxs(ha,{onClick:()=>De(ee),children:[c.jsx(vO,{className:"size-4"}),ee.enabled?"Disable":"Enable"]}),c.jsxs(ha,{variant:"destructive",onClick:()=>Ee(ee.id),children:[c.jsx(bc,{className:"size-4"}),"Delete"]})]})]}),ue?.jobId===ee.id&&c.jsx("span",{className:"text-muted-foreground text-xs",children:ue.message})]})})]},ee.id))})]})})})]}),c.jsx(Jc,{open:!!Q,onOpenChange:ee=>!ee&&Y(null),children:c.jsxs(Wc,{side:"right",className:"w-full max-w-lg overflow-y-auto",children:[c.jsxs(eu,{children:[c.jsxs(tu,{children:[Q?.name||Q?.id," — Run logs"]}),c.jsx(nu,{children:"Recent runs for this job. Status: pending, running, done, or failed."})]}),c.jsx("div",{className:"mt-4 space-y-3",children:Z?c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading…"}):A.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No runs yet. Use Test to run now."}):A.map(ee=>c.jsxs("div",{className:"border-input rounded-md border p-3 text-sm",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx(bt,{variant:ee.status==="done"?"default":ee.status==="failed"?"destructive":ee.status==="running"?"secondary":"outline",children:ee.status}),c.jsxs("span",{className:"text-muted-foreground font-mono text-xs",children:[ee.id.slice(0,16),"…"]})]}),c.jsxs("p",{className:"text-muted-foreground mt-1 text-xs",children:[ek(ee.created_at),ee.finished_at!=null&&ee.started_at!=null&&c.jsxs(c.Fragment,{children:[" · ",Math.round((ee.finished_at-ee.started_at)/1e3),"s"]})]}),ee.error&&c.jsx("p",{className:"mt-2 text-destructive text-xs",children:ee.error})]},ee.id))})]})})]})}function BP({config:e}){return c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Watched folders"}),c.jsx(kt,{children:"Paths monitored by the file watcher (from env and config/watched.json). Read-only."})]}),c.jsx(ct,{children:e?.watchFolders&&e.watchFolders.length>0?c.jsx("ul",{className:"space-y-2 font-mono text-sm",children:e.watchFolders.map(r=>c.jsx("li",{className:"rounded border bg-muted/30 px-3 py-2",children:r},r))}):c.jsx("p",{className:"text-muted-foreground text-sm",children:"No watched folders configured. Set WATCH_FOLDERS in .env or add paths to config/watched.json."})})]})}function HP(e){const[r,a]=S.useState(null);return S.useEffect(()=>{(e==="config"||e==="settings")&&Ka().then(a).catch(()=>a(null))},[e]),r}const Vb={OPENAI_API_KEY:"OpenAI API Key",ANTHROPIC_API_KEY:"Anthropic (Claude) API Key",GOOGLE_GEMINI_API_KEY:"Google Gemini API Key",GEMINI_API_KEY:"Gemini API Key (alt)",OPENROUTER_API_KEY:"OpenRouter API Key",OLLAMA_BASE_URL:"Ollama Base URL",GATEWAY_API_KEY:"Gateway API Key"};function FP(){const[e,r]=S.useState({}),[a,l]=S.useState({}),[s,u]=S.useState(!0),[d,f]=S.useState(!1),[h,p]=S.useState(null),[y,g]=S.useState(!1),[v,b]=S.useState(null),[k,j]=S.useState(null),[E,C]=S.useState(""),[M,O]=S.useState(""),[T,D]=S.useState([]),[R,P]=S.useState(!1),[B,$]=S.useState(!1),[U,ne]=S.useState(null);S.useEffect(()=>{Promise.all([sr(),Kl(),Ka(),Lw()]).then(([F,z,q,Q])=>{r(F.keys||{}),p(z.running),j(q??null),C(Q.defaultProvider??""),O(Q.defaultModel??"")}).catch(()=>b({type:"error",text:"Failed to load"})).finally(()=>u(!1))},[]),S.useEffect(()=>{if(!E||E!=="ollama"&&E!=="openrouter"){D([]);return}P(!0),Ss(E).then(F=>D(F.models??[])).catch(()=>D([])).finally(()=>P(!1))},[E]);const W=async()=>{g(!0);try{const{running:F}=await Kl();p(F)}finally{g(!1)}},ce=async()=>{f(!0),b(null);try{const F={};for(const[q,Q]of Object.entries(a))typeof Q=="string"&&Q.trim()&&(F[q]=Q.trim());await bs(F);const{keys:z}=await sr();r(z),l({}),b({type:"success",text:"API keys saved. Restart the agent for changes to take effect."})}catch(F){b({type:"error",text:F instanceof Error?F.message:"Failed to save"})}finally{f(!1)}},le=Object.keys(Vb);return s?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading…"})})}):c.jsxs("div",{className:"space-y-6",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"AI Providers"}),c.jsxs(kt,{children:["Add or update API keys. Saved to ",c.jsx("code",{className:"rounded bg-muted px-1 text-xs",children:"~/.sulala/.env"}),". Restart the agent for changes."]})]}),c.jsxs(ct,{className:"space-y-4",children:[le.map(F=>c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:F,children:Vb[F]??F}),c.jsx(Et,{id:F,type:"password",placeholder:e[F]==="set"?"(already set)":"",value:a[F]??"",onChange:z=>l(q=>({...q,[F]:z.target.value})),autoComplete:"off"})]},F)),v&&c.jsx("p",{className:v.type==="success"?"text-green-600 dark:text-green-400 text-sm":"text-destructive text-sm",children:v.text}),c.jsx(me,{onClick:ce,disabled:d||Object.keys(a).length===0,children:d?"Saving…":"Save"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"Default for scheduled jobs"}),c.jsx(kt,{children:'When a job uses "Use default", this provider and model are used. Set this to OpenRouter or OpenAI (not Ollama) so jobs run reliably even when Ollama is not running.'})]}),c.jsxs(ct,{className:"space-y-4",children:[c.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"job-default-provider",children:"Provider"}),c.jsxs("select",{id:"job-default-provider",className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:E,onChange:F=>{C(F.target.value),O("")},children:[c.jsx("option",{value:"",children:"Use env default"}),(k?.aiProviders??[]).filter(F=>F.id!=="ollama").map(F=>c.jsx("option",{value:F.id,children:F.label},F.id)),c.jsx("option",{value:"ollama",children:"Ollama (not recommended for jobs)"})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"job-default-model",children:"Model"}),E&&(E==="ollama"||E==="openrouter")?c.jsxs("select",{id:"job-default-model",className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:M,onChange:F=>O(F.target.value),disabled:R,children:[c.jsx("option",{value:"",children:"Use provider default"}),T.map(F=>c.jsx("option",{value:F.id,children:F.name},F.id))]}):c.jsx(Et,{id:"job-default-model",className:"h-9 text-sm",value:M,onChange:F=>O(F.target.value),placeholder:E?"e.g. gpt-4o-mini":"Set provider first",disabled:!E})]})]}),E==="ollama"&&c.jsx("p",{className:"text-amber-600 dark:text-amber-400 text-sm",children:"Ollama is not recommended for scheduled jobs. If Ollama is not running when the job runs, the job will fail."}),U&&c.jsx("p",{className:U.type==="success"?"text-green-600 dark:text-green-400 text-sm":"text-destructive text-sm",children:U.text}),c.jsx(me,{onClick:async()=>{$(!0),ne(null);try{await Pw({defaultProvider:E.trim()||null,defaultModel:M.trim()||null}),ne({type:"success",text:"Job default saved. New jobs using “Use default” will use this."})}catch(F){ne({type:"error",text:F instanceof Error?F.message:"Failed to save"})}finally{$(!1)}},disabled:B,children:B?"Saving…":"Save job default"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:"Ollama"}),c.jsx(kt,{children:"Local AI. No API key required. Install from ollama.com"})]}),c.jsxs(ct,{children:[h?c.jsx("p",{className:"text-green-600 dark:text-green-400 text-sm",children:"Ollama is running."}):c.jsx("p",{className:"text-muted-foreground text-sm",children:"Ollama is not running."}),c.jsx(me,{variant:"outline",size:"sm",onClick:W,disabled:y,className:"mt-2",children:y?"Checking…":"Check again"}),c.jsxs("p",{className:"text-muted-foreground mt-2 text-xs",children:["Install from ",c.jsx("a",{href:"https://ollama.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"ollama.com"})," or run ",c.jsx("code",{children:"ollama serve"})," in terminal."]})]})]})]})}function qP(e){const{tasks:r,load:a,enqueueType:l,setEnqueueType:s,enqueuePayload:u,setEnqueuePayload:d,enqueueing:f,actionTaskId:h,handleTaskCancel:p,handleTaskRetry:y,handleEnqueue:g}=e;return c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Enqueue task"}),c.jsx(kt,{children:"Add a task to the queue"})]}),c.jsxs(ct,{className:"flex flex-wrap items-end gap-4",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Type"}),c.jsx("input",{className:"border-input bg-background h-9 rounded-md border px-3 text-sm",value:l,onChange:v=>s(v.target.value),placeholder:"e.g. heartbeat"})]}),c.jsxs("div",{className:"min-w-[200px] space-y-2",children:[c.jsx("label",{className:"text-muted-foreground block text-sm",children:"Payload (JSON)"}),c.jsx("input",{className:"border-input bg-background h-9 w-full rounded-md border px-3 text-sm",value:u,onChange:v=>d(v.target.value),placeholder:'{"key": "value"}'})]}),c.jsx(me,{onClick:g,disabled:f,children:f?"Enqueueing…":"Enqueue"})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Tasks"}),c.jsx(kt,{children:"Recent tasks (from gateway)"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:a,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[400px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"ID"}),c.jsx(Zt,{children:"Type"}),c.jsx(Zt,{children:"Status"}),c.jsx(Zt,{children:"Created"}),c.jsx(Zt,{className:"w-[120px]",children:"Actions"})]})}),c.jsx(ep,{children:r.map(v=>c.jsxs(ga,{children:[c.jsxs(Ht,{className:"font-mono text-xs",children:[v.id.slice(0,20),"…"]}),c.jsx(Ht,{children:v.type}),c.jsx(Ht,{children:c.jsx(bt,{variant:v.status==="done"?"default":v.status==="failed"?"destructive":v.status==="cancelled"?"outline":"secondary",children:v.status})}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(v.created_at)}),c.jsxs(Ht,{children:[(v.status==="pending"||v.status==="running")&&c.jsx(me,{variant:"ghost",size:"sm",className:"h-7 text-destructive hover:text-destructive",disabled:h===v.id,onClick:()=>p(v.id),children:"Cancel"}),v.status==="failed"&&c.jsx(me,{variant:"ghost",size:"sm",className:"h-7",disabled:h===v.id,onClick:()=>y(v.id),children:"Retry"})]})]},v.id))})]})})})]})]})}function GP({logs:e,load:r}){return c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"Logs"}),c.jsx(kt,{children:"Recent gateway and worker logs"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:r,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[500px] rounded-md border p-3",children:c.jsx("div",{className:"space-y-1 font-mono text-xs",children:e.map(a=>c.jsxs("div",{className:"flex flex-wrap gap-2 border-b py-1.5 last:border-0",children:[c.jsx("span",{className:"text-muted-foreground shrink-0",children:ws(a.created_at)}),c.jsx(bt,{variant:"outline",className:"shrink-0",children:a.source}),c.jsx("span",{className:a.level==="error"?"text-destructive":a.level==="warn"?"text-amber-600 dark:text-amber-400":"",children:a.message})]},a.id))})})})]})}function $P({fileStates:e,load:r}){return c.jsxs(ot,{children:[c.jsxs(St,{className:"flex flex-row items-center justify-between",children:[c.jsxs("div",{children:[c.jsx(wt,{className:"text-base",children:"File states"}),c.jsx(kt,{children:"Files seen by the watcher (last modified time, size)"})]}),c.jsx(me,{variant:"outline",size:"sm",onClick:r,children:"Refresh"})]}),c.jsx(ct,{children:c.jsx(Wl,{className:"h-[500px]",children:c.jsxs(Jm,{children:[c.jsx(Wm,{children:c.jsxs(ga,{children:[c.jsx(Zt,{children:"Path"}),c.jsx(Zt,{children:"Size"}),c.jsx(Zt,{children:"Last seen"})]})}),c.jsx(ep,{children:e.length===0?c.jsx(ga,{children:c.jsx(Ht,{colSpan:3,className:"text-muted-foreground text-center",children:"No file states. Add watched folders and trigger file events."})}):e.map(a=>c.jsxs(ga,{children:[c.jsx(Ht,{className:"max-w-[400px] truncate font-mono text-xs",children:a.path}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:a.size!=null?`${a.size} B`:"—"}),c.jsx(Ht,{className:"text-muted-foreground text-xs",children:ws(a.last_seen)})]},a.path))})]})})})]})}const YP="https://discord.com/developers/applications";function VP(){const[e,r]=S.useState(null),[a,l]=S.useState(null),[s,u]=S.useState(!0),[d,f]=S.useState(!1),[h,p]=S.useState(null),[y,g]=S.useState(!1),[v,b]=S.useState(""),[k,j]=S.useState("open"),[E,C]=S.useState(""),[M,O]=S.useState(""),[T,D]=S.useState(""),[R,P]=S.useState([]),[B,$]=S.useState(!1),[U,ne]=S.useState(null),[W,ce]=S.useState(""),[le,F]=S.useState(!1),z=async()=>{u(!0),p(null);try{const[Y,A,L]=await Promise.all([uw(),fw(),Ka()]);r(Y),ne(A),l(L),g(Y.enabled),b(""),j(Y.dmPolicy||"open"),C(Array.isArray(Y.allowFrom)?Y.allowFrom.join(", "):""),O(Y.defaultProvider??""),D(Y.defaultModel??"")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{u(!1)}};S.useEffect(()=>{z()},[]),S.useEffect(()=>{if(!M||M!=="ollama"&&M!=="openrouter"){P([]);return}$(!0),Ss(M).then(Y=>P(Y.models??[])).catch(()=>P([])).finally(()=>$(!1))},[M]);const q=async()=>{f(!0),p(null);try{const Y=E.split(/[,;\s]+/).map(Z=>parseInt(Z.trim(),10)).filter(Z=>!Number.isNaN(Z)),A={enabled:y,dmPolicy:k,allowFrom:Y,defaultProvider:M.trim()||null,defaultModel:T.trim()||null};v.trim()&&(A.botToken=v.trim());const L=await dw(A);r(L),b("")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{f(!1)}},Q=async()=>{F(!0),p(null);try{const Y=await hw({botToken:W.trim()||null});ne(Y),ce("")}catch(Y){p(Y instanceof Error?Y.message:String(Y))}finally{F(!1)}};return s?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading channels…"})})}):c.jsxs("div",{className:"space-y-4",children:[c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Telegram"}),c.jsx(kt,{children:"Connect your device to Telegram so you can chat with the agent from your phone. Create a bot with @BotFather, then paste the token below."})]}),c.jsxs(ct,{className:"space-y-4",children:[e&&c.jsxs("div",{className:"space-y-1 text-sm",children:[c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),e.status==="connected"&&e.botUsername?c.jsxs("span",{className:"text-green-600 dark:text-green-400",children:["Connected as @",e.botUsername]}):e.configured?c.jsx("span",{className:"text-amber-600 dark:text-amber-400",children:"Not connected"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]}),e.error&&c.jsx("p",{className:"text-destructive text-xs",children:e.error}),e.configured&&!e.botUsername&&!e.error&&c.jsx("p",{className:"text-muted-foreground text-xs",children:"Click Save or Reconnect to start the bot. Use “Anyone” under Who can DM if you want to receive messages."})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("input",{type:"checkbox",id:"telegram-enabled",checked:y,onChange:Y=>g(Y.target.checked),className:"h-4 w-4 rounded border-input"}),c.jsx("label",{htmlFor:"telegram-enabled",className:"text-sm font-medium",children:"Enable Telegram channel"})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-token",className:"text-sm font-medium",children:"Bot token"}),c.jsx(Et,{id:"telegram-token",type:"password",placeholder:e?.configured?"(already set)":"123456789:ABC…",value:v,onChange:Y=>b(Y.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a token from @BotFather in Telegram. Leave blank to keep the current token."})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-dm-policy",className:"text-sm font-medium",children:"Who can DM the bot"}),c.jsxs("select",{id:"telegram-dm-policy",value:k,onChange:Y=>j(Y.target.value),className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"open",children:"Anyone"}),c.jsx("option",{value:"allowlist",children:"Only allowlist (set IDs below)"}),c.jsx("option",{value:"disabled",children:"Disabled"})]}),k==="disabled"&&c.jsx("p",{className:"text-muted-foreground text-xs",children:"Bot can still connect; it won’t reply to any DMs. Choose Anyone to chat from Telegram."})]}),k==="allowlist"&&c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"telegram-allow-from",className:"text-sm font-medium",children:"Allowed user IDs (comma-separated)"}),c.jsx(Et,{id:"telegram-allow-from",value:E,onChange:Y=>C(Y.target.value),placeholder:"123456789, 987654321",className:"font-mono text-sm"})]}),c.jsxs("div",{className:"space-y-2 border-t pt-4",children:[c.jsx("label",{className:"text-sm font-medium",children:"AI for Telegram"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Provider and model used when you chat via Telegram. Leave empty to use a connected provider (OpenRouter or OpenAI if configured, otherwise app default)."}),c.jsxs("div",{className:"grid gap-2 sm:grid-cols-2",children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx("label",{htmlFor:"telegram-provider",className:"text-xs text-muted-foreground",children:"Provider"}),c.jsxs("select",{id:"telegram-provider",value:M,onChange:Y=>{O(Y.target.value),D("")},className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"",children:"Use app default"}),(a?.aiProviders??[]).map(Y=>c.jsx("option",{value:Y.id,children:Y.label},Y.id))]})]}),c.jsxs("div",{className:"space-y-1",children:[c.jsx("label",{htmlFor:"telegram-model",className:"text-xs text-muted-foreground",children:"Model"}),M==="ollama"||M==="openrouter"?c.jsxs("select",{id:"telegram-model",value:T,onChange:Y=>D(Y.target.value),disabled:B,className:"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm",children:[c.jsx("option",{value:"",children:"Use provider default"}),R.map(Y=>c.jsx("option",{value:Y.id,children:Y.name},Y.id))]}):c.jsx(Et,{id:"telegram-model",value:T,onChange:Y=>D(Y.target.value),placeholder:M?"e.g. gpt-4o-mini":"Set provider first",disabled:!M,className:"h-9 text-sm"})]})]}),M==="ollama"&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support in Telegram, use a cloud provider."})})]}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsxs("div",{className:"flex flex-wrap gap-2",children:[c.jsxs(me,{onClick:q,disabled:d,children:[c.jsx(CO,{className:"size-4"}),d?"Saving…":"Save"]}),e?.configured&&e.status!=="connected"&&c.jsx(me,{variant:"outline",onClick:q,disabled:d,title:"Restart the bot with current settings",children:"Reconnect"})]})]})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Discord"}),c.jsx(kt,{children:"Let the agent post to your Discord servers. Create an app at the Discord Developer Portal, add a bot, invite it to your server with Send Messages, then paste the bot token below."})]}),c.jsxs(ct,{className:"space-y-4",children:[U&&c.jsx("div",{className:"space-y-1 text-sm",children:c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),U.configured?c.jsx("span",{className:"text-green-600 dark:text-green-400",children:"Configured"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]})}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"discord-token",className:"text-sm font-medium",children:"Bot token"}),c.jsx(Et,{id:"discord-token",type:"password",placeholder:U?.configured?"(already set)":"Paste your bot token…",value:W,onChange:Y=>ce(Y.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a token from the Discord Developer Portal (Bot section). Leave blank to keep the current token."})]}),c.jsxs("p",{className:"text-muted-foreground text-xs",children:[c.jsxs("a",{href:YP,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:["Open Discord Developer Portal",c.jsx(QS,{className:"size-3"})]})," ","→ create app, add bot, then OAuth2 → URL Generator (scope: bot, permissions: Send Messages) to invite the bot to your server."]}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsx(me,{onClick:Q,disabled:le,children:le?"Saving…":"Save"})]})]})]})}const KP="https://dashboard.stripe.com/apikeys";function XP(){const[e,r]=S.useState(null),[a,l]=S.useState(""),[s,u]=S.useState(!1),[d,f]=S.useState(!0),[h,p]=S.useState(null),y=async()=>{f(!0),p(null);try{const v=await mw();r(v)}catch(v){p(v instanceof Error?v.message:String(v))}finally{f(!1)}};S.useEffect(()=>{y()},[]);const g=async()=>{u(!0),p(null);try{const v=await pw({secretKey:a.trim()||null});r(v),l("")}catch(v){p(v instanceof Error?v.message:String(v))}finally{u(!1)}};return d?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading payment settings…"})})}):c.jsx("div",{className:"space-y-4",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{className:"text-base",children:"Stripe"}),c.jsx(kt,{children:"Let the agent list customers and invoices, and create invoices. Paste your Stripe Secret Key (from Dashboard → API keys). Use test key (sk_test_…) for development."})]}),c.jsxs(ct,{className:"space-y-4",children:[e&&c.jsx("div",{className:"space-y-1 text-sm",children:c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("span",{className:"text-muted-foreground",children:"Status:"}),e.configured?c.jsx("span",{className:"text-green-600 dark:text-green-400",children:"Configured"}):c.jsx("span",{className:"text-muted-foreground",children:"Not configured"})]})}),c.jsxs("div",{className:"space-y-2",children:[c.jsx("label",{htmlFor:"stripe-secret-key",className:"text-sm font-medium",children:"Secret key"}),c.jsx(Et,{id:"stripe-secret-key",type:"password",placeholder:e?.configured?"(already set)":"sk_test_… or sk_live_…",value:a,onChange:v=>l(v.target.value),autoComplete:"off",className:"font-mono text-sm"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Get a key from Stripe Dashboard → Developers → API keys. Leave blank to keep the current key."})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:c.jsxs("a",{href:KP,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:["Open Stripe API keys",c.jsx(QS,{className:"size-3"})]})}),h&&c.jsx("p",{className:"text-destructive text-sm",children:h}),c.jsx(me,{onClick:g,disabled:s,children:s?"Saving…":"Save"})]})]})})}function QP(){const[e,r]=S.useState(null),[a,l]=S.useState("session"),[s,u]=S.useState(""),[d,f]=S.useState([]),[h,p]=S.useState(!0),[y,g]=S.useState(!1),[v,b]=S.useState(null);S.useEffect(()=>{b(null),Qw().then(C=>{r(C),C.session.length>0?(l("session"),u(C.session[0])):C.shared.length>0&&(l("shared"),u(C.shared[0]))}).catch(C=>b(C instanceof Error?C.message:String(C))).finally(()=>p(!1))},[]);const k=a==="session"?e?.session??[]:e?.shared??[];S.useEffect(()=>{if(!s||!k.includes(s)){f([]);return}g(!0),Zw({scope:a,scope_key:s,limit:200}).then(C=>f(C.entries??[])).catch(C=>b(C instanceof Error?C.message:String(C))).finally(()=>g(!1))},[a,s]);const j=()=>{const C=new Blob([JSON.stringify({scope:a,scope_key:s,exported_at:new Date().toISOString(),entries:d},null,2)],{type:"application/json"}),M=document.createElement("a");M.href=URL.createObjectURL(C),M.download=`sulala-memory-${a}-${s.replace(/[^a-z0-9-_]/gi,"_")}.json`,M.click(),URL.revokeObjectURL(M.href)},E=C=>new Date(C).toLocaleString();return h?c.jsx(ot,{children:c.jsx(ct,{className:"pt-6",children:c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading memory…"})})}):c.jsx("div",{className:"space-y-4",children:c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsxs(wt,{className:"flex items-center gap-2 text-base",children:[c.jsx(VS,{className:"size-4"}),"Agent memory"]}),c.jsx(kt,{children:"View stored memory (session-scoped or shared across sessions). Use the chat to add entries via the write_memory tool."})]}),c.jsxs(ct,{className:"space-y-4",children:[v&&c.jsx("p",{className:"text-destructive text-sm",role:"alert",children:v}),c.jsxs("div",{className:"flex flex-wrap items-end gap-4",children:[c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"memory-scope",children:"Scope"}),c.jsxs("select",{id:"memory-scope",className:"flex h-9 w-[140px] rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",value:a,onChange:C=>{const M=C.target.value;l(M);const O=M==="session"?e?.session??[]:e?.shared??[];u(O[0]??"")},children:[c.jsx("option",{value:"session",children:"Session"}),c.jsx("option",{value:"shared",children:"Shared"})]})]}),c.jsxs("div",{className:"space-y-2",children:[c.jsx(Xt,{htmlFor:"memory-scope-key",children:a==="session"?"Session":"Shared key"}),c.jsx("select",{id:"memory-scope-key",className:"flex h-9 min-w-[200px] max-w-[320px] rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",value:s,onChange:C=>u(C.target.value),children:k.length===0?c.jsx("option",{value:"",children:"— No keys —"}):k.map(C=>c.jsx("option",{value:C,children:C.length>40?C.slice(0,37)+"…":C},C))})]}),d.length>0&&c.jsxs(me,{variant:"outline",size:"sm",onClick:j,children:[c.jsx(wR,{className:"size-4 mr-1"}),"Export JSON"]})]}),y&&c.jsx("p",{className:"text-muted-foreground text-sm",children:"Loading entries…"}),!y&&s&&k.includes(s)&&c.jsx("div",{className:"rounded-md border",children:d.length===0?c.jsxs("p",{className:"p-4 text-muted-foreground text-sm",children:["No memory entries for this ",a," key."]}):c.jsx("ul",{className:"divide-y divide-border max-h-[400px] overflow-y-auto",children:d.map(C=>c.jsxs("li",{className:"p-3 text-sm",children:[c.jsx("p",{className:"text-foreground",children:C.content}),c.jsx("p",{className:"mt-1 text-muted-foreground text-xs",children:E(C.created_at)})]},C.id))})})]})]})})}const xh="https://portal.sulala.ai/api/gateway";function ZP({required:e=!1,portalGatewayUrl:r,onSaved:a,onError:l,portalOAuthConnectAvailable:s=!1,onOAuthConnect:u}){const[d,f]=S.useState({}),[h,p]=S.useState(r?.trim()||xh),[y,g]=S.useState(""),[v,b]=S.useState(!1),[k,j]=S.useState(!1),[E,C]=S.useState(!1);S.useEffect(()=>{p(r?.trim()||xh)},[r]),S.useEffect(()=>{b(!0),sr().then(({keys:P})=>{f(P??{})}).catch(()=>f({})).finally(()=>b(!1))},[]);const M=async()=>{const P=h.trim();if(!P){l?.("Enter Portal gateway URL");return}if(e&&!y.trim()){l?.("Enter Portal API key");return}j(!0);try{const B={PORTAL_GATEWAY_URL:P};y.trim()&&(B.PORTAL_API_KEY=y.trim()),await bs(B);const{keys:$}=await sr();f($??{}),y.trim()&&g(""),a?.()}catch(B){l?.(B instanceof Error?B.message:"Failed to save")}finally{j(!1)}},O=d.PORTAL_API_KEY==="set"?"(already set)":"sk_live_...",T=k||!h.trim()||e&&!y.trim(),D=s&&u,R=async()=>{C(!0),l?.("");try{await u?.()}catch(P){l?.(P.message)}finally{C(!1)}};return c.jsxs("div",{className:"border-border bg-muted/30 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:e?"Portal API key required":"Portal settings"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:e?"Create an API key at your Portal and enter it below. Takes effect immediately.":"Connect GitHub, Gmail, and other apps via Portal. Saved keys take effect immediately."}),v?c.jsx("p",{className:"text-muted-foreground text-xs",children:"Loading…"}):c.jsxs("div",{className:"flex flex-col gap-3",children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"portal-gateway-url",className:"text-xs",children:"Portal gateway URL"}),c.jsx(Et,{id:"portal-gateway-url",type:"url",placeholder:xh,value:h,onChange:P=>p(P.target.value),className:"h-8 font-mono text-xs"}),c.jsx("p",{className:"text-muted-foreground text-[10px]",children:"e.g. http://localhost:3004/api/gateway for local Portal, or https://portal.sulala.ai/api/gateway"})]}),D&&c.jsxs(c.Fragment,{children:[c.jsx(me,{variant:"default",size:"sm",onClick:R,disabled:E,className:"w-fit",children:E?"Opening…":"Connect with Sulala (OAuth)"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Opens in a new tab. After signing in you’ll be redirected back; refresh this page if the key doesn’t appear."}),c.jsx("p",{className:"text-muted-foreground text-xs font-medium",children:"or"})]}),c.jsxs("form",{className:"space-y-3",onSubmit:P=>{P.preventDefault(),M()},children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"portal-api-key",className:"text-xs",children:"Portal API Key"}),c.jsx(Et,{id:"portal-api-key",type:"password",placeholder:O,value:y,onChange:P=>g(P.target.value),autoComplete:"off",className:"h-8"})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsx(me,{type:"submit",variant:"secondary",size:"sm",disabled:T,children:k?"Saving…":"Save"}),c.jsx("a",{href:(()=>{const P=h.trim();if(!P)return"https://portal.sulala.ai/api/keys";try{const B=P.replace(/\/api\/gateway$/i,""),$=/^https?:\/\//i.test(B)?B:`https://${B}`;return new URL("/api-keys",$).toString()}catch{return"https://portal.sulala.ai/api/keys"}})(),target:"_blank",rel:"noreferrer",className:"text-primary hover:underline text-xs",children:"Create API key →"})]})]})]})]})}function JP({storeBaseUrl:e,onSaved:r,onError:a}){const[l,s]=S.useState({}),[u,d]=S.useState(""),[f,h]=S.useState(!1),[p,y]=S.useState(!1);S.useEffect(()=>{h(!0),sr().then(({keys:k})=>s(k??{})).catch(()=>s({})).finally(()=>h(!1))},[]);const g=async()=>{y(!0);try{const k={};u.trim()&&(k.STORE_PUBLISH_API_KEY=u.trim()),await bs(k);const{keys:j}=await sr();s(j??{}),u.trim()&&d(""),r?.()}catch(k){a?.(k instanceof Error?k.message:"Failed to save")}finally{y(!1)}},v=l.STORE_PUBLISH_API_KEY==="set"?"(already set)":"sk_pub_...",b=e?`${e.replace(/\/$/,"")}/my-skills`:null;return c.jsxs("div",{className:"border-border bg-muted/30 flex flex-col gap-3 rounded-lg border p-4 text-sm",children:[c.jsx("p",{className:"font-medium",children:"Store publish API key"}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Publish skills from the dashboard (Skills → My skills → Publish to store). Create a key on the store (My skills → Create publish API key), then paste it here."}),f?c.jsx("p",{className:"text-muted-foreground text-xs",children:"Loading…"}):c.jsxs("form",{className:"flex flex-col gap-3",onSubmit:k=>{k.preventDefault(),g()},children:[c.jsxs("div",{className:"space-y-1",children:[c.jsx(Xt,{htmlFor:"store-publish-api-key",className:"text-xs",children:"API key"}),c.jsx(Et,{id:"store-publish-api-key",type:"password",placeholder:v,value:u,onChange:k=>d(k.target.value),autoComplete:"off",className:"h-8"})]}),c.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[c.jsx(me,{type:"submit",variant:"secondary",size:"sm",disabled:p,children:p?"Saving…":"Save"}),b&&c.jsx("a",{href:b,target:"_blank",rel:"noreferrer",className:"text-primary hover:underline text-xs",children:"Create API key on store →"})]})]})]})}const WP=[{value:"overview",label:"Overview",icon:KR},{value:"tasks",label:"Tasks",icon:nO},{value:"logs",label:"Logs",icon:jm},{value:"files",label:"File states",icon:IR},{value:"ai-providers",label:"AI Providers",icon:XS},{value:"channels",label:"Channels",icon:ns},{value:"payment",label:"Payment",icon:bR},{value:"memory",label:"Memory",icon:VS},{value:"portal",label:"Portal",icon:eO},{value:"config",label:"Watched folders",icon:nw}];function eU(e){return c.jsx("div",{className:"flex flex-1 flex-col min-h-0",children:c.jsx(au,{defaultValue:"overview",orientation:"vertical",className:"flex flex-1 flex-col min-h-0",children:c.jsxs("div",{className:"flex flex-1 min-h-0",children:[c.jsx(lu,{variant:"line",className:"w-52 shrink-0 flex flex-col h-auto rounded-none p-2 gap-0.5",children:WP.map(({value:r,label:a,icon:l})=>c.jsxs(pa,{value:r,className:Se("w-full justify-start gap-2 rounded-md px-3 py-2 h-auto font-normal","data-[state=active]:bg-background data-[state=active]:shadow-sm data-[state=active]:font-medium"),children:[c.jsx(l,{className:"size-4 shrink-0"}),c.jsx("span",{className:"truncate",children:a})]},r))}),c.jsxs("div",{className:"flex-1 min-w-0 overflow-auto p-4",children:[c.jsx(Vt,{value:"overview",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(T4,{health:e.health,loading:e.loading,connected:e.connected,events:e.events})}),c.jsx(Vt,{value:"tasks",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(qP,{tasks:e.tasks,loading:e.loading,load:e.load,enqueueType:e.enqueueType,setEnqueueType:e.setEnqueueType,enqueuePayload:e.enqueuePayload,setEnqueuePayload:e.setEnqueuePayload,enqueueing:e.enqueueing,actionTaskId:e.actionTaskId,handleTaskCancel:e.handleTaskCancel,handleTaskRetry:e.handleTaskRetry,handleEnqueue:e.handleEnqueue})}),c.jsx(Vt,{value:"logs",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(GP,{logs:e.logs,load:e.load})}),c.jsx(Vt,{value:"files",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx($P,{fileStates:e.fileStates,load:e.load})}),c.jsx(Vt,{value:"ai-providers",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(FP,{})}),c.jsx(Vt,{value:"channels",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(VP,{})}),c.jsx(Vt,{value:"payment",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(XP,{})}),c.jsx(Vt,{value:"memory",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(QP,{})}),c.jsx(Vt,{value:"portal",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(tU,{config:e.config,onError:e.onError})}),c.jsx(Vt,{value:"config",className:"mt-0 flex-1 data-[state=inactive]:hidden",children:c.jsx(BP,{config:e.config})})]})]})})})}function tU({config:e,onError:r}){const a=e?.portalGatewayUrl??null,l=e?.portalOAuthConnectAvailable===!0,s=async()=>{const{url:d}=await Nm();window.open(d,"_blank","noopener,noreferrer")},u=Jl();return c.jsxs("div",{className:"flex flex-col gap-4",children:[c.jsx(ZP,{portalGatewayUrl:a,onError:r,portalOAuthConnectAvailable:l,onOAuthConnect:l?s:void 0}),c.jsx(JP,{storeBaseUrl:u,onError:r})]})}const nU=100;function rU(e){const[r,a]=S.useState([]),[l,s]=S.useState(!1),u=S.useRef(null),d=S.useRef(e?.onSkillsChanged);return d.current=e?.onSkillsChanged,S.useEffect(()=>{const f=Cw(),h=new WebSocket(f);return h.onopen=()=>s(!0),h.onclose=()=>s(!1),h.onmessage=p=>{try{const y=JSON.parse(p.data);a(g=>[y,...g].slice(0,nU)),y.type==="skills_changed"&&d.current&&d.current()}catch{}},h.onerror=()=>{},u.current=h,()=>{h.close(),u.current=null,s(!1)}},[]),{events:r,connected:l}}function aU({className:e,checked:r,onCheckedChange:a,onChange:l,...s}){const u=r===!0;return c.jsx("input",{type:"checkbox",checked:u,onChange:d=>{l?.(d),a?.(d.target.checked)},"data-slot":"checkbox",className:Se("border-input size-4 shrink-0 rounded border transition-colors","focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-2","accent-primary disabled:opacity-50",e),...s})}const lU="modulepreload",iU=function(e){return"/"+e},Kb={},sU=function(r,a,l){let s=Promise.resolve();if(a&&a.length>0){let p=function(y){return Promise.all(y.map(g=>Promise.resolve(g).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};var d=p;document.getElementsByTagName("link");const f=document.querySelector("meta[property=csp-nonce]"),h=f?.nonce||f?.getAttribute("nonce");s=p(a.map(y=>{if(y=iU(y),y in Kb)return;Kb[y]=!0;const g=y.endsWith(".css"),v=g?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${y}"]${v}`))return;const b=document.createElement("link");if(b.rel=g?"stylesheet":lU,g||(b.as="script"),b.crossOrigin="",b.href=y,h&&b.setAttribute("nonce",h),document.head.appendChild(b),g)return new Promise((k,j)=>{b.addEventListener("load",k),b.addEventListener("error",()=>j(new Error(`Unable to preload CSS for ${y}`)))})}))}function u(f){const h=new Event("vite:preloadError",{cancelable:!0});if(h.payload=f,window.dispatchEvent(h),!h.defaultPrevented)throw f}return s.then(f=>{for(const h of f||[])h.status==="rejected"&&u(h.reason);return r().catch(u)})},uj=[{id:"openrouter",label:"OpenRouter",envKey:"OPENROUTER_API_KEY",apiKeyUrl:"https://openrouter.ai/keys"},{id:"ollama",label:"Ollama (Local – No API Key Required)",envKey:null,apiKeyUrl:null},{id:"openai",label:"OpenAI",envKey:"OPENAI_API_KEY",apiKeyUrl:"https://platform.openai.com/api-keys"},{id:"anthropic",label:"Anthropic (Claude)",envKey:"ANTHROPIC_API_KEY",apiKeyUrl:"https://console.anthropic.com/settings/keys"},{id:"google",label:"Google / Gemini",envKey:"GOOGLE_GEMINI_API_KEY",apiKeyUrl:"https://aistudio.google.com/app/apikey"}],oU={openai:"OPENAI_API_KEY",anthropic:"ANTHROPIC_API_KEY",google:"GOOGLE_GEMINI_API_KEY",gemini:"GEMINI_API_KEY",openrouter:"OPENROUTER_API_KEY"};function cU(e){const[r,a]=S.useState({statusLoading:!0,statusComplete:null,step:0,selectedProviders:[],envKeys:{},envKeysInput:{},recommendedModels:[],registrySkills:[],selectedSkills:[],ollamaRunning:null,ollamaStatusLoading:!1,pullState:{inProgress:!1,model:"",lastLine:"",percent:0},pullingModels:new Set,loading:!1,error:null,systemCapabilities:null}),l=S.useCallback(async()=>{a(T=>({...T,statusLoading:!0}));try{const{complete:T}=await Cm();return a(D=>({...D,statusComplete:T,statusLoading:!1})),T}catch(T){return a(D=>({...D,statusComplete:!1,statusLoading:!1,error:T instanceof Error?T.message:"Failed to load status"})),!1}},[]),s=S.useCallback(async()=>{try{const{keys:T}=await sr();return a(D=>({...D,envKeys:T})),T}catch{return{}}},[]),u=S.useCallback(async()=>{try{const{models:T}=await yw();return a(D=>({...D,recommendedModels:T})),T}catch{return[]}},[]),d=S.useCallback(async()=>{try{const{skills:T}=await wc();return a(D=>({...D,registrySkills:T})),T}catch{return[]}},[]),f=S.useCallback(async()=>{a(T=>({...T,ollamaStatusLoading:!0}));try{const{running:T}=await Kl();return a(D=>({...D,ollamaRunning:T,ollamaStatusLoading:!1})),T}catch{return a(T=>({...T,ollamaRunning:!1,ollamaStatusLoading:!1})),!1}},[]),h=S.useCallback(async()=>{const{fetchOllamaPullStatus:T}=await sU(async()=>{const{fetchOllamaPullStatus:R}=await Promise.resolve().then(()=>j4);return{fetchOllamaPullStatus:R}},void 0),D=await T();return a(R=>({...R,pullState:D})),D},[]);S.useEffect(()=>{l()},[l]);const p=S.useCallback(async()=>{try{const T=await Uw();return a(D=>({...D,systemCapabilities:T})),T}catch{return a(T=>({...T,systemCapabilities:null})),null}},[]);return S.useEffect(()=>{r.step===0&&p()},[r.step,p]),S.useEffect(()=>{(r.step===1||r.step===2)&&s()},[r.step,s]),S.useEffect(()=>{r.step===2&&r.selectedProviders.includes("ollama")&&(u(),f())},[r.step,r.selectedProviders,u,f]),S.useEffect(()=>{r.step===4&&d()},[r.step,d]),S.useEffect(()=>{if(!r.pullState.inProgress)return;const T=setInterval(h,500);return()=>clearInterval(T)},[r.pullState.inProgress,h]),{...r,loadStatus:l,loadSystemCapabilities:p,installOllama:async()=>{a(T=>({...T,error:null}));try{await Iw(),await f()}catch(T){a(D=>({...D,error:T instanceof Error?T.message:"Failed to install Ollama"}))}},loadEnv:s,loadRecommendedModels:u,loadRegistrySkills:d,checkOllama:f,setStep:T=>a(D=>({...D,step:T})),setSelectedProviders:T=>a(D=>({...D,selectedProviders:T})),setEnvKeysInput:T=>a(D=>({...D,envKeysInput:T})),setSelectedSkills:T=>a(D=>({...D,selectedSkills:T})),setError:T=>a(D=>({...D,error:T})),saveEnv:async(T,D)=>{a(R=>({...R,loading:!0,error:null}));try{const R=r.envKeysInput,P={...D};for(const[$,U]of Object.entries(R))typeof U=="string"&&U.trim()&&(P[$]=U.trim());await bs(P);const{keys:B}=await sr();a($=>({...$,envKeys:B,envKeysInput:{},loading:!1,step:T??2}))}catch(R){a(P=>({...P,loading:!1,error:R instanceof Error?R.message:"Failed to save API keys"}))}},pullModel:async T=>{a(D=>({...D,pullingModels:new Set(D.pullingModels).add(T),error:null}));try{await vw(T),h()}catch(D){a(R=>({...R,pullingModels:(()=>{const P=new Set(R.pullingModels);return P.delete(T),P})(),error:D instanceof Error?D.message:"Failed to pull model"}))}},installSkill:async T=>{a(D=>({...D,loading:!0,error:null}));try{await Tm(T,"managed"),a(D=>({...D,selectedSkills:[...new Set([...D.selectedSkills,T])],loading:!1}))}catch(D){a(R=>({...R,loading:!1,error:D instanceof Error?D.message:"Failed to install skill"}))}},finishOnboarding:async()=>{a(T=>({...T,loading:!0,error:null}));try{await xw(),a(T=>({...T,statusComplete:!0,loading:!1})),e?.()}catch(T){a(D=>({...D,loading:!1,error:T instanceof Error?T.message:"Failed to complete onboarding"}))}}}}function uU(e){if(!e)return null;const r=e.match(/~?(\d+(?:\.\d+)?)\s*(GB|MB|gb|mb)/);if(!r)return null;const a=parseFloat(r[1]),l=r[2].toUpperCase();return l==="GB"?Math.round(a*1024*1024*1024):l==="MB"?Math.round(a*1024*1024):null}const dj=S.createContext(null);function Es(){const e=S.useContext(dj);if(!e)throw new Error("OnboardingFlow must wrap steps");return e}const dU=["Choose AI Provider","Provider Configuration","Integrations","Ollama Model Setup","Finish"],fU=["Choose AI Provider","Provider Configuration","Integrations","Finish"];function hU(){const{selectedProviders:e,setSelectedProviders:r,setStep:a,systemCapabilities:l}=Es(),s=l&&!l.ollamaSuitable,u=f=>{if(f==="ollama"&&s)return;const h=e.includes(f)?e.filter(p=>p!==f):[...e,f];r(h)},d=e.length>=1;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("p",{className:"text-muted-foreground text-sm",children:"Select at least one AI provider to continue. Ollama runs locally and needs no API key."}),s&&l&&c.jsxs("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:[c.jsxs("p",{className:"text-amber-700 dark:text-amber-400",children:["⚠️ ",l.ollamaSuitableReason]}),c.jsx("p",{className:"text-muted-foreground mt-1 text-xs",children:"Use a cloud provider (OpenAI, OpenRouter, etc.) instead."})]}),e.includes("ollama")&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support and best results, add a cloud provider."})}),c.jsx("div",{className:"grid gap-3",children:uj.map(f=>c.jsxs("label",{className:`border-input flex items-center gap-3 rounded-lg border p-4 transition-colors ${f.id==="ollama"&&s?"cursor-not-allowed opacity-60":"hover:bg-muted/50 cursor-pointer"}`,children:[c.jsx(aU,{checked:e.includes(f.id),onCheckedChange:()=>u(f.id),disabled:f.id==="ollama"&&!!s}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"font-medium",children:f.label}),f.id==="ollama"&&s&&c.jsx("div",{className:"text-amber-600 dark:text-amber-400 mt-0.5 text-xs",children:"Not available on this system"}),f.envKey&&c.jsxs("div",{className:"text-muted-foreground mt-0.5 flex flex-wrap items-center gap-x-2 text-xs",children:[c.jsx("span",{children:"Requires API key"}),"apiKeyUrl"in f&&typeof f.apiKeyUrl=="string"&&c.jsx("a",{href:f.apiKeyUrl,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:"Get API key →"})]})]})]},f.id))}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx("div",{}),c.jsxs(me,{disabled:!d,onClick:()=>a(1),children:["Next",c.jsx(zr,{className:"ml-1 size-4"})]})]})]})}function mU(){const{selectedProviders:e,envKeys:r,envKeysInput:a,setEnvKeysInput:l,saveEnv:s,setStep:u,loading:d,error:f}=Es(),h=e.filter(j=>j!=="ollama"),p={OPENAI_API_KEY:"OpenAI API Key",ANTHROPIC_API_KEY:"Anthropic API Key",GOOGLE_GEMINI_API_KEY:"Google Gemini API Key",GEMINI_API_KEY:"Gemini API Key (alt)",OPENROUTER_API_KEY:"OpenRouter API Key"},y={};uj.forEach(j=>{j.envKey&&"apiKeyUrl"in j&&typeof j.apiKeyUrl=="string"&&(y[j.envKey]=j.apiKeyUrl)});const g=h.flatMap(j=>{const E=oU[j];return E?[E]:[]}),b=!g.some(j=>r[j]!=="set")||g.length===0,k=g.some(j=>(a[j]??"").trim().length>0);return c.jsxs("div",{className:"space-y-6",children:[h.length===0?c.jsx("p",{className:"text-muted-foreground text-sm",children:"No cloud providers selected. Skipping API keys."}):c.jsxs(c.Fragment,{children:[c.jsxs("p",{className:"text-muted-foreground text-sm",children:["Enter API keys for selected providers. Keys are saved securely to ",c.jsx("code",{className:"rounded bg-muted px-1 text-xs",children:"~/.sulala/.env"}),"."]}),c.jsx("div",{className:"grid gap-4",children:g.map(j=>c.jsxs("div",{className:"space-y-2",children:[c.jsxs("div",{className:"flex flex-wrap items-center gap-x-2",children:[c.jsx(Xt,{htmlFor:j,children:p[j]??j}),y[j]&&c.jsx("a",{href:y[j],target:"_blank",rel:"noopener noreferrer",className:"text-primary text-xs hover:underline",children:"Get API key →"})]}),c.jsx(Et,{id:j,type:"password",placeholder:r[j]==="set"?"(already set)":"sk-...",value:a[j]??"",onChange:E=>l({...a,[j]:E.target.value}),autoComplete:"off"})]},j))})]}),f&&c.jsx("div",{className:"text-destructive text-sm",children:f}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>u(0),children:"Back"}),c.jsxs("div",{className:"flex gap-2",children:[(b||k)&&c.jsx(me,{variant:"outline",onClick:()=>u(2),children:h.length===0?"Next":"Skip for now"}),k&&c.jsx(me,{onClick:()=>s(2),disabled:d,children:d?"Saving…":"Save & Next"}),b&&!k&&h.length>0&&c.jsx(me,{onClick:()=>u(2),children:"Next"})]})]})]})}function pU(){const{setStep:e,selectedProviders:r}=Es(),l=r.includes("ollama")?4:3;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("p",{className:"text-muted-foreground text-sm",children:"You can connect apps (GitHub, Gmail, Twitter, etc.) in two ways:"}),c.jsxs("ul",{className:"text-muted-foreground list-disc list-inside space-y-1 text-sm",children:[c.jsxs("li",{children:[c.jsx("strong",{children:"MCP Servers"})," — Integrations → MCP Servers tab. Add servers and API keys (e.g. YouTube, Twitter). Find more at"," ",c.jsx("a",{href:"https://mcpservers.org/",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline hover:no-underline",children:"mcpservers.org"}),"."]}),c.jsxs("li",{children:[c.jsx("strong",{children:"Sulala Portal"})," — To use Portal for OAuth apps, add your API key later in ",c.jsx("strong",{children:"Settings → Portal"}),"."]})]}),c.jsx("p",{className:"text-muted-foreground text-xs",children:"Neither is required now. You can set up either option anytime from the dashboard."}),c.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[c.jsx(me,{variant:"outline",onClick:()=>e(1),children:"Back"}),c.jsxs(me,{onClick:()=>e(l),children:["Next",c.jsx(zr,{className:"ml-1 size-4"})]})]})]})}function gU({m:e,installed:r,pulling:a,onPull:l}){return c.jsxs("div",{className:"border-input flex flex-col gap-2 rounded-lg border p-4 sm:flex-row sm:items-center sm:justify-between",children:[c.jsxs("div",{children:[c.jsx("div",{className:"font-medium",children:e.name}),c.jsx("div",{className:"text-muted-foreground text-sm",children:e.description}),c.jsxs("div",{className:"mt-1 flex flex-wrap gap-2 text-xs",children:[c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(ZS,{className:"size-3"})," ",e.size]}),c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(YO,{className:"size-3"})," ",e.ram," RAM"]}),c.jsxs("span",{className:"flex items-center gap-1",children:[c.jsx(XS,{className:"size-3"})," ",e.cpu]}),e.gpu!=="None"&&c.jsxs("span",{children:["GPU: ",e.gpu]})]})]}),c.jsx(me,{variant:r?"secondary":"default",size:"sm",onClick:l,disabled:r||a,children:r?"Installed":a?"Installing…":"Install"})]})}function xU(){const{recommendedModels:e,ollamaRunning:r,ollamaStatusLoading:a,pullState:l,pullingModels:s,pullModel:u,installOllama:d,setStep:f,checkOllama:h,systemCapabilities:p,error:y}=Es(),g=()=>{window.confirm("Ollama will be downloaded and installed (~500MB). This requires network access and sufficient disk space. Continue?")&&d()},v=j=>{const E=p?.storageFreeBytes??0,C=uU(j.size);if(C!=null&&E>0&&C>E){alert(`Insufficient storage. This model needs ~${j.size}. You have ${(E/1024/1024/1024).toFixed(1)}GB free.`);return}window.confirm(`Download and install ${j.name}? This will use ~${j.size} of disk space. Continue?`)&&u(j.id)},b=new Set;l.inProgress&&l.model&&b.add(l.model);const k=p&&!p.ollamaSuitable;return c.jsxs("div",{className:"space-y-6",children:[c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsx("p",{className:"text-amber-700 dark:text-amber-400",children:"⚠️ Ollama cannot run tools and perform like other providers (e.g. OpenAI, OpenRouter). For full tool support and best results, use a cloud provider."})}),k&&c.jsx("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-3 text-sm",children:c.jsxs("p",{className:"text-amber-700 dark:text-amber-400",children:["⚠️ ",p.ollamaSuitableReason," Ollama may not run well here."]})}),a?c.jsx("p",{className:"text-muted-foreground text-sm",children:"Checking Ollama…"}):r===!1?c.jsxs("div",{className:"rounded-lg border border-amber-500/50 bg-amber-500/10 p-4",children:[c.jsxs("p",{className:"text-amber-700 dark:text-amber-400 text-sm",children:["⚠️ Ollama is not running. Click Install to download Ollama, or install from"," ",c.jsx("a",{href:"https://ollama.com",target:"_blank",rel:"noopener noreferrer",className:"underline",children:"ollama.com"})," ","and run ",c.jsx("code",{children:"ollama serve"}),"."]}),c.jsxs("div",{className:"mt-2 flex gap-2",children:[c.jsx(me,{variant:"default",size:"sm",onClick:g,disabled:a,children:"Install Ollama"}),c.jsx(me,{variant:"outline",size:"sm",onClick:h,disabled:a,children:"Check again"})]})]}):null,l.inProgress&&c.jsxs("div",{className:"rounded-lg border border-blue-500/50 bg-blue-500/10 p-4",children:[c.jsxs("div",{className:"font-medium",children:["Pulling ",l.model,"…"]}),l.percent>=0&&l.percent<=100&&c.jsx(Om,{value:l.percent,className:"mt-2 h-2"}),l.lastLine&&c.jsx("div",{className:"text-muted-foreground mt-1 truncate font-mono text-xs",children:l.lastLine})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Select models to install. You can skip and install later from Settings."}),c.jsx("div",{className:"grid gap-3",children:e.map(j=>c.jsx(gU,{m:j,installed:!1,pulling:s.has(j.id),onPull:()=>v(j)},j.id))}),y&&c.jsx("div",{className:"text-destructive text-sm",children:y}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>f(2),children:"Back"}),c.jsx(me,{onClick:()=>f(4),children:"Skip or Next"})]})]})}function Xb(){const{selectedProviders:e,finishOnboarding:r,loading:a,error:l,setStep:s}=Es(),u=e.includes("ollama");return c.jsxs("div",{className:"space-y-6",children:[c.jsxs("div",{children:[c.jsx("h3",{className:"font-semibold",children:"Summary"}),c.jsx("ul",{className:"text-muted-foreground mt-2 space-y-1 text-sm",children:c.jsxs("li",{className:"flex items-center gap-2",children:[c.jsx(KS,{className:"size-4 text-green-600"}),"AI providers: ",e.join(", ")||"None"]})})]}),c.jsx("p",{className:"text-muted-foreground text-sm",children:"Click Finish to complete onboarding and open the dashboard. You can change providers anytime in Settings."}),l&&c.jsx("div",{className:"text-destructive text-sm",children:l}),c.jsxs("div",{className:"flex justify-between",children:[c.jsx(me,{variant:"outline",onClick:()=>s(u?3:2),children:"Back"}),c.jsx(me,{onClick:r,disabled:a,children:a?"Finishing…":"Finish"})]})]})}function yU({onComplete:e}){const r=cU(e),{step:a,selectedProviders:l}=r,s=l.includes("ollama"),u=s?5:4,d=s?dU:fU,f=Math.max(0,Math.min(a,u-1)),h={0:"Choose which AI providers you want to use.",1:"Enter API keys for cloud providers.",2:"Connect apps via MCP servers or Sulala Portal (optional). Add Portal API key in Settings → Portal if you use Portal.",...s?{3:"Install local models with Ollama.",4:"Review and complete setup."}:{3:"Review and complete setup."}};return c.jsx(dj.Provider,{value:r,children:c.jsx("div",{className:"bg-background flex min-h-screen flex-col items-center justify-center p-4",children:c.jsxs("div",{className:"w-full max-w-2xl space-y-8",children:[c.jsxs("div",{className:"text-center",children:[c.jsx("h1",{className:"text-2xl font-bold",children:"Welcome to Sulala"}),c.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["Step ",f+1," of ",u,": ",d[f]]}),c.jsx(Om,{value:(f+1)/u*100,className:"mt-4 h-2"})]}),c.jsxs(ot,{children:[c.jsxs(St,{children:[c.jsx(wt,{children:d[f]}),c.jsx(kt,{children:h[f]})]}),c.jsxs(ct,{children:[f===0&&c.jsx(hU,{}),f===1&&c.jsx(mU,{}),f===2&&c.jsx(pU,{}),f===3&&(s?c.jsx(xU,{}):c.jsx(Xb,{})),f===4&&s&&c.jsx(Xb,{})]})]})]})})})}function vU(){const[e,r]=S.useState(null),[a,l]=S.useState(()=>{if(typeof window>"u")return"chat";const C=new URLSearchParams(window.location.search).get("page");return["chat","skills","integrations","jobs","settings","overview","tasks","logs","files","config"].includes(C)?C:"chat"}),[s,u]=S.useState(null);S.useEffect(()=>{console.log("fetching onboarding status"),Cm().then(({complete:C})=>{console.log("onboarding status",C),r(C)}).catch(C=>{console.error("error fetching onboarding status",C);const M=C.message||String(C);r(!!(M.includes("429")||M.includes("fetch")))})},[]);const[d,f]=S.useState(null),h=C4(C=>u(C)),p=_4(C=>u(C)),y=J4(a,C=>u(C),{onMissingIntegrations:C=>f(C)}),g=RP(a,C=>u(C)),v=HP(a);S.useEffect(()=>{(a==="settings"||a==="jobs")&&h.load()},[a]);const b=S.useRef(()=>{});b.current=p.loadSkills;const{events:k,connected:j}=rU({onSkillsChanged:()=>b.current?.()});if(S.useEffect(()=>{a==="skills"&&p.loadSkillsData()},[a]),e===null)return c.jsx("div",{className:"bg-background flex min-h-screen flex-col items-center justify-center",children:c.jsx("div",{className:"text-muted-foreground text-sm",children:"Loading…"})});if(!e)return c.jsx(bU,{onComplete:()=>{window.location.reload()}});const E=C=>{if(l(C),typeof window<"u"){const M=new URL(window.location.href);M.searchParams.set("page",C),window.history.replaceState({},"",M.toString())}};return c.jsxs(w4,{activePage:a,onNavigate:E,error:s,children:[a==="chat"&&c.jsx(MP,{...y,integrations:g.integrations,onNavigateToIntegrations:()=>E("integrations"),missingIntegrationsFromServer:d,onClearMissingIntegrationsFromServer:()=>f(null)}),a==="skills"&&c.jsx(q4,{...p}),a==="integrations"&&c.jsx(zP,{...g,onError:C=>u(C)}),a==="jobs"&&c.jsx(IP,{schedules:h.schedules,loading:h.loading,load:h.load,onCreateSchedule:h.handleCreateSchedule,onUpdateSchedule:h.handleUpdateSchedule,onDeleteSchedule:h.handleDeleteSchedule,onRunSchedule:h.handleRunSchedule,onFetchScheduleRuns:h.handleFetchScheduleRuns}),a==="settings"&&c.jsx(eU,{health:h.health,loading:h.loading,connected:j,events:k,tasks:h.tasks,load:h.load,enqueueType:h.enqueueType,setEnqueueType:h.setEnqueueType,enqueuePayload:h.enqueuePayload,setEnqueuePayload:h.setEnqueuePayload,enqueueing:h.enqueueing,actionTaskId:h.actionTaskId,handleTaskCancel:h.handleTaskCancel,handleTaskRetry:h.handleTaskRetry,handleEnqueue:h.handleEnqueue,logs:h.logs,fileStates:h.fileStates,config:v,onError:C=>u(C)})]})}function bU({onComplete:e}){return c.jsx(yU,{onComplete:e})}zC.createRoot(document.getElementById("root")).render(c.jsx(S.StrictMode,{children:c.jsx(vU,{})}));