@apteva/apteva-linux-x64 0.4.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apteva +0 -0
- package/dist/ActivityPage.41nbye4r.js +3 -0
- package/dist/ActivityPage.41nbye4r.js.map +9 -0
- package/dist/ApiDocsPage.4smnt8m3.js +4 -0
- package/dist/ApiDocsPage.4smnt8m3.js.map +10 -0
- package/dist/App.0sbax9et.js +4 -0
- package/dist/App.0sbax9et.js.map +10 -0
- package/dist/App.0ws427h8.js +4 -0
- package/dist/App.0ws427h8.js.map +10 -0
- package/dist/App.6q6bar8b.js +4 -0
- package/dist/App.6q6bar8b.js.map +10 -0
- package/dist/App.80301vdb.js +4 -0
- package/dist/App.80301vdb.js.map +10 -0
- package/dist/App.af2wg84v.js +267 -0
- package/dist/App.af2wg84v.js.map +35 -0
- package/dist/App.ca1rz1ph.js +4 -0
- package/dist/App.ca1rz1ph.js.map +14 -0
- package/dist/App.ensa6z0r.js +4 -0
- package/dist/App.ensa6z0r.js.map +10 -0
- package/dist/App.f8g7tych.js +13 -0
- package/dist/App.f8g7tych.js.map +10 -0
- package/dist/App.mvtqv6qc.js +20 -0
- package/dist/App.mvtqv6qc.js.map +14 -0
- package/dist/App.ncgc9cxy.js +4 -0
- package/dist/App.ncgc9cxy.js.map +10 -0
- package/dist/App.p02f4ret.js +1 -0
- package/dist/App.p0fb1pds.js +4 -0
- package/dist/App.p0fb1pds.js.map +10 -0
- package/dist/App.pmaq48sj.js +4 -0
- package/dist/App.pmaq48sj.js.map +10 -0
- package/dist/App.yv87t9m5.js +4 -0
- package/dist/App.yv87t9m5.js.map +10 -0
- package/dist/App.zjmfm8p6.js +4 -0
- package/dist/App.zjmfm8p6.js.map +10 -0
- package/dist/ConnectionsPage.anb3rv9a.js +3 -0
- package/dist/ConnectionsPage.anb3rv9a.js.map +9 -0
- package/dist/McpPage.y396h6fy.js +3 -0
- package/dist/McpPage.y396h6fy.js.map +9 -0
- package/dist/SettingsPage.p1hc60gk.js +3 -0
- package/dist/SettingsPage.p1hc60gk.js.map +9 -0
- package/dist/SkillsPage.yj3xdsay.js +3 -0
- package/dist/SkillsPage.yj3xdsay.js.map +9 -0
- package/dist/TasksPage.sjv0khtv.js +3 -0
- package/dist/TasksPage.sjv0khtv.js.map +9 -0
- package/dist/TelemetryPage.2qm4w16r.js +3 -0
- package/dist/TelemetryPage.2qm4w16r.js.map +9 -0
- package/dist/TestsPage.zzs4qfj8.js +3 -0
- package/dist/TestsPage.zzs4qfj8.js.map +9 -0
- package/dist/apteva-kit.css +1 -0
- package/dist/icon.png +0 -0
- package/dist/index.html +16 -0
- package/dist/styles.css +1 -0
- package/index.js +1 -0
- package/package.json +10 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{G as n,l as g,m as o}from"./App.ncgc9cxy.js";import{N as t,O as V}from"./App.yv87t9m5.js";import{R as d}from"./App.p0fb1pds.js";import{S as i,V as e,W as a,ca as v,fa as D}from"./App.mvtqv6qc.js";var H=i(e(),1);var q=i(a(),1);function Oq(){let{projectsEnabled:z,metaAgentEnabled:Z}=D(),[W,B]=H.useState("general"),M=[{key:"general",label:"General"},{key:"providers",label:"Providers"},...z?[{key:"projects",label:"Projects"}]:[],...Z?[{key:"assistant",label:"Assistant"}]:[],{key:"channels",label:"Channels"},{key:"api-keys",label:"API Keys"},{key:"account",label:"Account"},{key:"updates",label:"Updates"},{key:"data",label:"Data"}];return q.jsxDEV("div",{className:"flex-1 flex flex-col md:flex-row overflow-hidden",children:[q.jsxDEV("div",{className:"md:hidden border-b border-[#1a1a1a] bg-[#0a0a0a]",children:q.jsxDEV("div",{className:"flex overflow-x-auto",style:{scrollbarWidth:"none",msOverflowStyle:"none"},children:M.map((Q)=>q.jsxDEV("button",{onClick:()=>B(Q.key),className:`flex-shrink-0 px-4 py-3 text-sm font-medium border-b-2 transition ${W===Q.key?"border-[#f97316] text-[#f97316]":"border-transparent text-[#666] hover:text-[#888]"}`,children:Q.label},Q.key,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this),q.jsxDEV("div",{className:"hidden md:block w-48 border-r border-[#1a1a1a] p-4 flex-shrink-0",children:[q.jsxDEV("h2",{className:"text-sm font-medium text-[#666] uppercase tracking-wider mb-3",children:"Settings"},void 0,!1,void 0,this),q.jsxDEV("nav",{className:"space-y-1",children:M.map((Q)=>q.jsxDEV(qq,{label:Q.label,active:W===Q.key,onClick:()=>B(Q.key)},Q.key,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex-1 overflow-auto p-4 md:p-6",children:[W==="general"&&q.jsxDEV(zq,{},void 0,!1,void 0,this),W==="providers"&&q.jsxDEV(Hq,{},void 0,!1,void 0,this),W==="projects"&&z&&q.jsxDEV(Qq,{},void 0,!1,void 0,this),W==="channels"&&q.jsxDEV(Jq,{},void 0,!1,void 0,this),W==="api-keys"&&q.jsxDEV($q,{},void 0,!1,void 0,this),W==="account"&&q.jsxDEV(Gq,{},void 0,!1,void 0,this),W==="updates"&&q.jsxDEV(Yq,{},void 0,!1,void 0,this),W==="data"&&q.jsxDEV(Wq,{},void 0,!1,void 0,this),W==="assistant"&&Z&&q.jsxDEV(_q,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function qq({label:z,active:Z,onClick:W}){return q.jsxDEV("button",{onClick:W,className:`w-full text-left px-3 py-2 rounded text-sm transition ${Z?"bg-[#1a1a1a] text-[#e0e0e0]":"text-[#666] hover:bg-[#111] hover:text-[#888]"}`,children:z},void 0,!1,void 0,this)}function zq(){let{authFetch:z}=v(),[Z,W]=H.useState(""),[B,M]=H.useState(!0),[Q,L]=H.useState(!1),[_,N]=H.useState(null);H.useEffect(()=>{(async()=>{try{let O=await(await z("/api/settings/instance-url")).json();W(O.instance_url||"")}catch{}M(!1)})()},[]);let J=async()=>{L(!0),N(null);try{let T=await z("/api/settings/instance-url",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({instance_url:Z})}),I=await T.json();if(T.ok)W(I.instance_url||""),N({type:"success",text:"Instance URL saved"});else N({type:"error",text:I.error||"Failed to save"})}catch{N({type:"error",text:"Failed to save"})}L(!1)};return q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"General"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:"Instance configuration."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:[q.jsxDEV("h3",{className:"font-medium mb-2",children:"Instance URL"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666] mb-4",children:"The public HTTPS URL for this instance. Used for webhook callbacks from external services like Composio."},void 0,!1,void 0,this),B?q.jsxDEV("div",{className:"text-[#666] text-sm",children:"Loading..."},void 0,!1,void 0,this):q.jsxDEV("div",{className:"space-y-3 max-w-lg",children:[q.jsxDEV("input",{type:"text",value:Z,onChange:(T)=>W(T.target.value),placeholder:"https://your-domain.com",className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316] font-mono text-sm"},void 0,!1,void 0,this),_&&q.jsxDEV("div",{className:`p-3 rounded text-sm ${_.type==="success"?"bg-green-500/10 text-green-400 border border-green-500/30":"bg-red-500/10 text-red-400 border border-red-500/30"}`,children:_.text},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:J,disabled:Q,className:"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black rounded text-sm font-medium transition",children:Q?"Saving...":"Save"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Hq(){let{authFetch:z}=v(),{projects:Z,projectsEnabled:W}=D(),[B,M]=H.useState([]),[Q,L]=H.useState(null),[_,N]=H.useState(""),[J,T]=H.useState(""),[I,O]=H.useState(!1),[R,X]=H.useState(!1),[w,U]=H.useState(null),[F,b]=H.useState(null),{confirm:k,ConfirmDialog:f}=V(),u=async()=>{let l=await(await z("/api/providers")).json();M(l.providers||[])};H.useEffect(()=>{u()},[]);let h=async()=>{if(!Q||!_)return;O(!0),U(null),b(null);let $=_;if(Q==="browserbase"&&J)$=JSON.stringify({api_key:_,project_id:J});try{X(!0);let m=await(await z(`/api/keys/${Q}/test`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:$})})).json();if(X(!1),!m.valid){U(m.error||"API key is invalid"),O(!1);return}let x=await z(`/api/keys/${Q}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:$})}),c=await x.json();if(!x.ok)U(c.error||"Failed to save key");else{let A="API key saved!";if(c.restartedAgents&&c.restartedAgents.length>0){let S=c.restartedAgents.filter((j)=>j.success).length;if(c.restartedAgents.length-S===0)A+=` Restarted ${S} agent${S>1?"s":""} with new key.`;else A+=` Restarted ${S}/${c.restartedAgents.length} agents.`}b(A),N(""),T(""),L(null),u()}}catch(l){U("Failed to save key")}O(!1)},C=async($)=>{if(!await k("Are you sure you want to remove this API key?",{confirmText:"Remove",title:"Remove API Key"}))return;await z(`/api/keys/${$}`,{method:"DELETE"}),u()},G=B.filter(($)=>$.type==="llm"),Y=B.filter(($)=>$.type==="integration"),P=B.filter(($)=>$.type==="browser"),K=G.filter(($)=>$.hasKey).length,y=Y.filter(($)=>$.hasKey).length,p=P.filter(($)=>$.hasKey).length;return H.useEffect(()=>{if(F&&!Q){let $=setTimeout(()=>b(null),5000);return()=>clearTimeout($)}},[F,Q]),q.jsxDEV(q.Fragment,{children:[f,q.jsxDEV("div",{className:"space-y-10",children:[F&&!Q&&q.jsxDEV("div",{className:"bg-green-500/10 border border-green-500/30 rounded-lg p-4 flex items-center justify-between",children:[q.jsxDEV("div",{className:"flex items-center gap-2 text-green-400",children:[q.jsxDEV(g,{className:"w-5 h-5"},void 0,!1,void 0,this),q.jsxDEV("span",{children:F},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>b(null),className:"text-green-400 hover:text-green-300",children:q.jsxDEV(o,{className:"w-4 h-4"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"AI Providers"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:["Manage your API keys for AI providers. ",K," of ",G.length," configured."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:G.map(($)=>q.jsxDEV(r,{provider:$,isEditing:Q===$.id,apiKey:_,saving:I,testing:R,error:Q===$.id?w:null,success:Q===$.id?F:null,onStartEdit:()=>{L($.id),U(null),b(null)},onCancelEdit:()=>{L(null),N(""),U(null)},onApiKeyChange:N,onSave:h,onDelete:()=>C($.id)},$.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h2",{className:"text-xl font-semibold mb-1",children:"MCP Integrations"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:["Connect to MCP gateways for tool integrations. ",y," of ",Y.length," configured."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:Y.map(($)=>q.jsxDEV(Zq,{provider:$,isEditing:Q===$.id,apiKey:_,saving:I,testing:R,error:Q===$.id?w:null,success:Q===$.id?F:null,onStartEdit:()=>{L($.id),U(null),b(null)},onCancelEdit:()=>{L(null),N(""),U(null)},onApiKeyChange:N,onSave:h,onDelete:()=>C($.id),projectsEnabled:W,projects:Z,onRefresh:u},$.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h2",{className:"text-xl font-semibold mb-1",children:"Browser Providers"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:["Configure browser environments for operator mode (computer use). ",p," of ",P.length," configured."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:P.map(($)=>q.jsxDEV(r,{provider:$,isEditing:Q===$.id,apiKey:_,saving:I,testing:R,error:Q===$.id?w:null,success:Q===$.id?F:null,onStartEdit:()=>{L($.id),U(null),b(null)},onCancelEdit:()=>{L(null),N(""),T(""),U(null)},onApiKeyChange:N,onSave:h,onDelete:()=>C($.id),extraField:J,onExtraFieldChange:T},$.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var E=["#f97316","#6366f1","#22c55e","#ef4444","#3b82f6","#a855f7","#14b8a6","#f59e0b"];function Qq(){let{projects:z,createProject:Z,updateProject:W,deleteProject:B}=D(),[M,Q]=H.useState(!1),[L,_]=H.useState(null),{confirm:N,ConfirmDialog:J}=V(),T=async(X)=>{if(!await N("Are you sure you want to delete this project? Agents in this project will become unassigned.",{confirmText:"Delete",title:"Delete Project"}))return;await B(X)},I=()=>{_(null),Q(!0)},O=(X)=>{_(X),Q(!0)},R=()=>{Q(!1),_(null)};return q.jsxDEV(q.Fragment,{children:[J,q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6 flex items-center justify-between gap-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"Projects"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:"Organize agents into projects for better management."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:I,className:"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition flex-shrink-0",children:[q.jsxDEV(n,{className:"w-4 h-4"},void 0,!1,void 0,this),"New Project"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.length===0?q.jsxDEV("div",{className:"text-center py-12 text-[#666]",children:[q.jsxDEV("p",{className:"text-lg mb-2",children:"No projects yet"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm",children:"Create a project to organize your agents."},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"space-y-3",children:z.map((X)=>q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 flex items-center gap-4",children:[q.jsxDEV("div",{className:"w-4 h-4 rounded-full flex-shrink-0",style:{backgroundColor:X.color}},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("h3",{className:"font-medium",children:X.name},void 0,!1,void 0,this),X.description&&q.jsxDEV("p",{className:"text-sm text-[#666] truncate",children:X.description},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#666] mt-1",children:[X.agentCount," agent",X.agentCount!==1?"s":""]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2",children:[q.jsxDEV("button",{onClick:()=>O(X),className:"text-sm text-[#888] hover:text-[#e0e0e0] px-2 py-1",children:"Edit"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>T(X.id),className:"text-sm text-red-400 hover:text-red-300 px-2 py-1",children:"Delete"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),M&&q.jsxDEV(Xq,{project:L,onSave:async(X)=>{if(L){let w=await W(L.id,X);if(w)R();return!!w}else{let w=await Z(X);if(w)R();return!!w}},onClose:R},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Xq({project:z,onSave:Z,onClose:W}){let[B,M]=H.useState(z?.name||""),[Q,L]=H.useState(z?.description||""),[_,N]=H.useState(z?.color||E[Math.floor(Math.random()*E.length)]),[J,T]=H.useState(!1),[I,O]=H.useState(null),R=async()=>{if(!B.trim()){O("Name is required");return}T(!0),O(null);let X=await Z({name:B,description:Q||void 0,color:_});if(T(!1),!X)O(z?"Failed to update project":"Failed to create project")};return q.jsxDEV(t,{onClose:W,children:[q.jsxDEV("h2",{className:"text-xl font-semibold mb-6",children:z?"Edit Project":"Create New Project"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"space-y-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Name"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"text",value:B,onChange:(X)=>M(X.target.value),className:"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]",placeholder:"My Project",autoFocus:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Description (optional)"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"text",value:Q,onChange:(X)=>L(X.target.value),className:"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]",placeholder:"A short description"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Color"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex gap-3 flex-wrap",children:E.map((X)=>q.jsxDEV("button",{type:"button",onClick:()=>N(X),className:`w-10 h-10 rounded-full transition ${_===X?"ring-2 ring-white ring-offset-2 ring-offset-[#111]":"hover:scale-110"}`,style:{backgroundColor:X}},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I&&q.jsxDEV("p",{className:"text-red-400 text-sm",children:I},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex gap-3 mt-6",children:[q.jsxDEV("button",{onClick:W,className:"flex-1 border border-[#333] hover:border-[#f97316] hover:text-[#f97316] px-4 py-2 rounded font-medium transition",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:R,disabled:J||!B.trim(),className:"flex-1 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition",children:J?"Saving...":z?"Update":"Create"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Yq(){let{authFetch:z}=v(),[Z,W]=H.useState(null),[B,M]=H.useState(!1),[Q,L]=H.useState(!1),[_,N]=H.useState(null),[J,T]=H.useState(null),[I,O]=H.useState(null),R=async()=>{M(!0),N(null);try{let F=await z("/api/version");if(!F.ok)throw Error("Failed to check for updates");let b=await F.json();W(b)}catch(F){N("Failed to check for updates")}M(!1)},X=async()=>{L(!0),N(null),T(null);try{let b=await(await z("/api/version/update",{method:"POST"})).json();if(!b.success)N(b.error||"Update failed");else{let k=b.restarted?.length||0,f=k>0?` ${k} running agent${k>1?"s":""} restarted.`:"";T(`Agent binary updated to v${b.version}.${f}`),await R()}}catch(F){N("Failed to update agent")}L(!1)};H.useEffect(()=>{R()},[]);let w=(F,b)=>{navigator.clipboard.writeText(F),O(b),setTimeout(()=>O(null),2000)},U=Z?.apteva.updateAvailable||Z?.agent.updateAvailable;return q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"Updates"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:"Check for new versions of apteva and the agent binary."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B&&!Z?q.jsxDEV("div",{className:"text-[#666]",children:"Checking version info..."},void 0,!1,void 0,this):_&&!Z?q.jsxDEV("div",{className:"text-red-400",children:_},void 0,!1,void 0,this):Z?.isDocker?q.jsxDEV("div",{className:"space-y-6",children:[q.jsxDEV("div",{className:"bg-blue-500/10 border border-blue-500/30 rounded-lg p-4",children:[q.jsxDEV("div",{className:"flex items-center gap-2 text-blue-400 mb-2",children:[q.jsxDEV("svg",{className:"w-5 h-5",fill:"currentColor",viewBox:"0 0 24 24",children:q.jsxDEV("path",{d:"M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.186.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.186.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.186.186 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.186.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.185-.186H5.136a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"},void 0,!1,void 0,this)},void 0,!1,void 0,this),q.jsxDEV("span",{className:"font-medium",children:"Docker Environment"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#888]",children:"Updates are automatic when you pull a new image version."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-5",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("h3",{className:"font-medium text-lg",children:"Current Version"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:"apteva + agent binary"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"text-right",children:q.jsxDEV("div",{className:"text-xl font-mono",children:["v",Z.apteva.installed||"?"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U?q.jsxDEV("div",{className:"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4",children:[q.jsxDEV("p",{className:"text-sm text-[#888] mb-3",children:["A newer version (v",Z.apteva.latest,") is available. To update:"]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"space-y-2",children:[q.jsxDEV("code",{className:"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]",children:"docker pull apteva/apteva:latest"},void 0,!1,void 0,this),q.jsxDEV("code",{className:"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]",children:"docker compose up -d"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>{navigator.clipboard.writeText("docker pull apteva/apteva:latest && docker compose up -d"),O("docker"),setTimeout(()=>O(null),2000)},className:"mt-3 px-3 py-1.5 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm",children:I==="docker"?"Copied!":"Copy commands"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center gap-2 text-green-400 text-sm",children:[q.jsxDEV(g,{className:"w-4 h-4"},void 0,!1,void 0,this),"Up to date"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#555]",children:"Your data is stored in a Docker volume and persists across updates."},void 0,!1,void 0,this)]},void 0,!0,void 0,this):Z?q.jsxDEV("div",{className:"space-y-6",children:[J&&q.jsxDEV("div",{className:"bg-green-500/10 border border-green-500/30 rounded-lg p-4 text-green-400",children:J},void 0,!1,void 0,this),_&&q.jsxDEV("div",{className:"bg-red-500/10 border border-red-500/30 rounded-lg p-4 text-red-400",children:_},void 0,!1,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-5",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("h3",{className:"font-medium text-lg",children:"apteva"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:"The app you're running"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"text-right",children:[q.jsxDEV("div",{className:"text-xl font-mono",children:["v",Z.apteva.installed||"?"]},void 0,!0,void 0,this),Z.apteva.updateAvailable&&q.jsxDEV("div",{className:"text-sm text-[#f97316]",children:["→ v",Z.apteva.latest]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z.apteva.updateAvailable?q.jsxDEV("div",{className:"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4",children:[q.jsxDEV("p",{className:"text-sm text-[#888] mb-3",children:"Update by running:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2",children:[q.jsxDEV("code",{className:"flex-1 bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]",children:"npx apteva@latest"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>w("npx apteva@latest","apteva"),className:"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm",children:I==="apteva"?"Copied!":"Copy"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center gap-2 text-green-400 text-sm",children:[q.jsxDEV(g,{className:"w-4 h-4"},void 0,!1,void 0,this),"Up to date"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-5",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("h3",{className:"font-medium text-lg",children:"Agent Binary"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:"The Go binary that runs agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"text-right",children:[q.jsxDEV("div",{className:"text-xl font-mono",children:["v",Z.agent.installed||"?"]},void 0,!0,void 0,this),Z.agent.updateAvailable&&q.jsxDEV("div",{className:"text-sm text-[#f97316]",children:["→ v",Z.agent.latest]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z.agent.updateAvailable?q.jsxDEV("div",{className:"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4",children:[q.jsxDEV("p",{className:"text-sm text-[#888] mb-3",children:"A new version is available. Stop all agents before updating."},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2",children:q.jsxDEV("button",{onClick:X,disabled:Q,className:"px-4 py-2 bg-[#f97316] text-black rounded font-medium text-sm disabled:opacity-50",children:Q?"Updating...":"Update Agent"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center gap-2 text-green-400 text-sm",children:[q.jsxDEV(g,{className:"w-4 h-4"},void 0,!1,void 0,this),"Up to date"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),!U&&!J&&q.jsxDEV("div",{className:"bg-green-500/10 border border-green-500/30 rounded-lg p-4 flex items-center gap-2 text-green-400",children:[q.jsxDEV(g,{className:"w-5 h-5"},void 0,!1,void 0,this),"Everything is up to date!"]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:R,disabled:B,className:"text-sm text-[#666] hover:text-[#888] disabled:opacity-50",children:B?"Checking...":"Check for updates"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)}function r({provider:z,isEditing:Z,apiKey:W,saving:B,testing:M,error:Q,success:L,onStartEdit:_,onCancelEdit:N,onApiKeyChange:J,onSave:T,onDelete:I,extraField:O,onExtraFieldChange:R}){let X=z.id==="ollama",w=X||z.id==="browserengine"||z.id==="chrome",U=z.type==="browser",F=z.id==="browserbase",[b,k]=H.default.useState(null);return H.default.useEffect(()=>{if(X&&z.hasKey)fetch("/api/providers/ollama/status").then((f)=>f.json()).then((f)=>k({connected:f.connected,modelCount:f.modelCount})).catch(()=>k({connected:!1}))},[X,z.hasKey]),q.jsxDEV("div",{className:`bg-[#111] border rounded-lg p-4 ${z.hasKey?"border-green-500/20":"border-[#1a1a1a]"}`,children:[q.jsxDEV("div",{className:"flex items-start justify-between gap-2 mb-2",children:[q.jsxDEV("div",{className:"min-w-0",children:[q.jsxDEV("h3",{className:"font-medium",children:z.name},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666] truncate",children:U?z.description||"Browser automation":z.type==="integration"?z.description||"MCP integration":X?"Run models locally":`${z.models.length} models`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.hasKey?q.jsxDEV("span",{className:`text-xs flex items-center gap-1 px-2 py-1 rounded whitespace-nowrap flex-shrink-0 ${X&&b?b.connected?"text-green-400 bg-green-500/10":"text-yellow-400 bg-yellow-500/10":"text-green-400 bg-green-500/10"}`,children:X&&b?b.connected?q.jsxDEV(q.Fragment,{children:[q.jsxDEV(g,{className:"w-3 h-3"},void 0,!1,void 0,this),b.modelCount," models"]},void 0,!0,void 0,this):q.jsxDEV(q.Fragment,{children:"Not running"},void 0,!1,void 0,this):w?q.jsxDEV(q.Fragment,{children:[q.jsxDEV(g,{className:"w-3 h-3"},void 0,!1,void 0,this),"Configured"]},void 0,!0,void 0,this):q.jsxDEV(q.Fragment,{children:[q.jsxDEV(g,{className:"w-3 h-3"},void 0,!1,void 0,this),z.keyHint]},void 0,!0,void 0,this)},void 0,!1,void 0,this):q.jsxDEV("span",{className:"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded whitespace-nowrap flex-shrink-0",children:"Not configured"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mt-3 pt-3 border-t border-[#1a1a1a]",children:Z?q.jsxDEV("div",{className:"space-y-3",children:[F?q.jsxDEV(q.Fragment,{children:[q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#888] mb-1",children:"API Key"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"password",value:W,onChange:(f)=>J(f.target.value),placeholder:z.hasKey?"Enter new API key...":"Enter API key...",autoFocus:!0,className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#888] mb-1",children:"Project ID"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"text",value:O||"",onChange:(f)=>R?.(f.target.value),placeholder:"Enter your Browserbase project ID...",className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("input",{type:w?"text":"password",value:W,onChange:(f)=>J(f.target.value),placeholder:X?"http://localhost:11434":z.id==="browserengine"?"http://localhost:8098":z.id==="chrome"?"http://localhost:9222":z.hasKey?"Enter new API key...":"Enter API key...",autoFocus:!0,className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this),w&&q.jsxDEV("p",{className:"text-xs text-[#666]",children:X?"Enter your Ollama server URL. Default is http://localhost:11434":z.id==="browserengine"?"Enter your BrowserEngine service URL (e.g., http://localhost:8098)":"Enter your Chrome DevTools URL (e.g., http://localhost:9222)"},void 0,!1,void 0,this),Q&&q.jsxDEV("p",{className:"text-red-400 text-sm",children:Q},void 0,!1,void 0,this),L&&q.jsxDEV("p",{className:"text-green-400 text-sm",children:L},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex gap-2",children:[q.jsxDEV("button",{onClick:N,className:"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:T,disabled:!W||B,className:"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50",children:M?"Validating...":B?"Saving...":w?"Connect":"Save"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):z.hasKey?q.jsxDEV("div",{className:"flex items-center justify-between",children:[z.docsUrl?q.jsxDEV("a",{href:z.docsUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-[#3b82f6] hover:underline",children:X?"Download Ollama":"View docs"},void 0,!1,void 0,this):q.jsxDEV("span",{},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-3",children:[q.jsxDEV("button",{onClick:_,className:"text-sm text-[#888] hover:text-[#e0e0e0]",children:w?"Change URL":"Update key"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:I,className:"text-red-400 hover:text-red-300 text-sm",children:"Remove"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center justify-between",children:[z.docsUrl?q.jsxDEV("a",{href:z.docsUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-[#3b82f6] hover:underline",children:X?"Download Ollama":U?"View docs":"Get API key"},void 0,!1,void 0,this):q.jsxDEV("span",{},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:_,className:"text-sm text-[#f97316] hover:text-[#fb923c]",children:w?"Configure":"+ Add key"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Zq({provider:z,isEditing:Z,apiKey:W,saving:B,testing:M,error:Q,success:L,onStartEdit:_,onCancelEdit:N,onApiKeyChange:J,onSave:T,onDelete:I,projectsEnabled:O,projects:R,onRefresh:X}){let{authFetch:w}=v(),[U,F]=H.useState([]),[b,k]=H.useState(""),[f,u]=H.useState(!1),[h,C]=H.useState(null),[G,Y]=H.useState(!1),{confirm:P,ConfirmDialog:K}=V(),y=async()=>{try{let S=await(await w(`/api/keys/${z.id}`)).json();F(S.keys||[])}catch(A){console.error("Failed to fetch keys:",A)}};H.useEffect(()=>{if(O)y()},[z.id,O]),H.useEffect(()=>{if(Z)C(null)},[Z]);let p=async()=>{if(!W)return;Y(!0),C(null);try{let A=await w(`/api/keys/${z.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:W,project_id:b||null})}),S=await A.json();if(A.ok)J(""),k(""),N(),y(),X();else C(S.error||"Failed to save key")}catch(A){console.error("Failed to save key:",A),C("Failed to save key")}Y(!1)},$=async(A,S)=>{if(!await P(`Are you sure you want to remove this API key${S?` (${S})`:""}?`,{confirmText:"Remove",title:"Remove API Key"}))return;try{await w(`/api/keys/by-id/${A}`,{method:"DELETE"}),y(),X()}catch(j){console.error("Failed to delete key:",j)}},l=U.find((A)=>!A.project_id),m=U.filter((A)=>A.project_id),x=(A)=>R.find((S)=>S.id===A)?.name||"Unknown",c=(A)=>R.find((S)=>S.id===A)?.color||"#666";if(!O)return q.jsxDEV("div",{className:`bg-[#111] border rounded-lg p-4 ${z.hasKey?"border-[#f97316]/20":"border-[#1a1a1a]"}`,children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-2",children:[q.jsxDEV("div",{children:[q.jsxDEV("h3",{className:"font-medium",children:z.name},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:z.description||"MCP integration"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.hasKey?q.jsxDEV("span",{className:"text-[#f97316] text-xs flex items-center gap-1 bg-[#f97316]/10 px-2 py-1 rounded",children:[q.jsxDEV(g,{className:"w-3 h-3"},void 0,!1,void 0,this),z.keyHint]},void 0,!0,void 0,this):q.jsxDEV("span",{className:"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded",children:"Not configured"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mt-3 pt-3 border-t border-[#1a1a1a]",children:Z?q.jsxDEV("div",{className:"space-y-3",children:[q.jsxDEV("input",{type:"password",value:W,onChange:(A)=>J(A.target.value),placeholder:z.hasKey?"Enter new API key...":"Enter API key...",autoFocus:!0,className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this),Q&&q.jsxDEV("p",{className:"text-red-400 text-sm",children:Q},void 0,!1,void 0,this),L&&q.jsxDEV("p",{className:"text-green-400 text-sm",children:L},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex gap-2",children:[q.jsxDEV("button",{onClick:N,className:"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:T,disabled:!W||B,className:"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50",children:M?"Validating...":B?"Saving...":"Save"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):z.hasKey?q.jsxDEV("div",{className:"flex items-center justify-between",children:[q.jsxDEV("a",{href:z.docsUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-[#3b82f6] hover:underline",children:"View docs"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-3",children:[q.jsxDEV("button",{onClick:_,className:"text-sm text-[#888] hover:text-[#e0e0e0]",children:"Update key"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:I,className:"text-red-400 hover:text-red-300 text-sm",children:"Remove"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center justify-between",children:[q.jsxDEV("a",{href:z.docsUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-[#3b82f6] hover:underline",children:"Get API key"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:_,className:"text-sm text-[#f97316] hover:text-[#fb923c]",children:"+ Add key"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return q.jsxDEV(q.Fragment,{children:[K,q.jsxDEV("div",{className:`bg-[#111] border rounded-lg p-4 ${U.length>0?"border-[#f97316]/20":"border-[#1a1a1a]"}`,children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-2",children:[q.jsxDEV("div",{children:[q.jsxDEV("h3",{className:"font-medium",children:z.name},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:z.description||"MCP integration"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U.length>0?q.jsxDEV("span",{className:"text-[#f97316] text-xs flex items-center gap-1 bg-[#f97316]/10 px-2 py-1 rounded",children:[q.jsxDEV(g,{className:"w-3 h-3"},void 0,!1,void 0,this),U.length," key",U.length!==1?"s":""]},void 0,!0,void 0,this):q.jsxDEV("span",{className:"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded",children:"Not configured"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U.length>0&&q.jsxDEV("div",{className:"mt-3 space-y-2",children:[l&&q.jsxDEV("div",{className:"flex items-center justify-between text-sm bg-[#0a0a0a] rounded px-3 py-2",children:[q.jsxDEV("div",{className:"flex items-center gap-2",children:[q.jsxDEV("span",{className:"text-[#888]",children:"Global"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#555]",children:"·"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#666] font-mono text-xs",children:l.key_hint},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>$(l.id,"Global"),className:"text-red-400 hover:text-red-300 text-xs",children:"Remove"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),m.slice(0,f?void 0:2).map((A)=>q.jsxDEV("div",{className:"flex items-center justify-between text-sm bg-[#0a0a0a] rounded px-3 py-2",children:[q.jsxDEV("div",{className:"flex items-center gap-2 min-w-0",children:[q.jsxDEV("span",{className:"w-2 h-2 rounded-full flex-shrink-0",style:{backgroundColor:c(A.project_id)}},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#888] truncate",children:A.name||x(A.project_id)},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#555]",children:"·"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#666] font-mono text-xs",children:A.key_hint},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>$(A.id,A.name||x(A.project_id)),className:"text-red-400 hover:text-red-300 text-xs flex-shrink-0 ml-2",children:"Remove"},void 0,!1,void 0,this)]},A.id,!0,void 0,this)),m.length>2&&!f&&q.jsxDEV("button",{onClick:()=>u(!0),className:"text-xs text-[#666] hover:text-[#888] w-full text-center py-1",children:["Show ",m.length-2," more..."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mt-3 pt-3 border-t border-[#1a1a1a]",children:Z?q.jsxDEV("div",{className:"space-y-3",children:[q.jsxDEV("input",{type:"password",value:W,onChange:(A)=>J(A.target.value),placeholder:"Enter API key...",autoFocus:!0,className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this),q.jsxDEV(d,{value:b,onChange:k,placeholder:"Global (all projects)",options:[{value:"",label:"Global (all projects)"},...R.map((A)=>({value:A.id,label:A.name}))]},void 0,!1,void 0,this),h&&q.jsxDEV("p",{className:"text-red-400 text-sm",children:h},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex gap-2",children:[q.jsxDEV("button",{onClick:()=>{N(),k(""),C(null)},className:"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:p,disabled:!W||G,className:"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50",children:G?"Saving...":"Save"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"flex items-center justify-between",children:[q.jsxDEV("a",{href:z.docsUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-[#3b82f6] hover:underline",children:U.length>0?"View docs":"Get API key"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:_,className:"text-sm text-[#f97316] hover:text-[#fb923c]",children:"+ Add key"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function $q(){let{authFetch:z}=v(),[Z,W]=H.useState([]),[B,M]=H.useState(!1),[Q,L]=H.useState(""),[_,N]=H.useState("90"),[J,T]=H.useState(!1),[I,O]=H.useState(null),[R,X]=H.useState(null),[w,U]=H.useState(!1),{confirm:F,ConfirmDialog:b}=V(),k=async()=>{try{let P=await(await z("/api/keys/personal")).json();W(P.keys||[])}catch{}};H.useEffect(()=>{k()},[]);let f=async()=>{if(!Q.trim()){O("Name is required");return}T(!0),O(null);try{let Y=await z("/api/keys/personal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Q.trim(),expires_in_days:_?parseInt(_):null})}),P=await Y.json();if(!Y.ok)O(P.error||"Failed to create key");else X(P.key),L(""),N("90"),k()}catch{O("Failed to create key")}T(!1)},u=async(Y,P)=>{if(!await F(`Delete API key "${P}"? This cannot be undone.`,{confirmText:"Delete",title:"Delete API Key"}))return;try{await z(`/api/keys/personal/${Y}`,{method:"DELETE"}),k()}catch{}},h=()=>{if(R)navigator.clipboard.writeText(R),U(!0),setTimeout(()=>U(!1),2000)},C=(Y)=>{if(!Y)return"Never";return new Date(Y).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})},G=(Y)=>{if(!Y)return!1;return new Date(Y)<new Date};return q.jsxDEV(q.Fragment,{children:[b,q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6 flex items-center justify-between gap-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"API Keys"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:["Create personal API keys for programmatic access. Use them with the ",q.jsxDEV("code",{className:"text-[#888] bg-[#1a1a1a] px-1 rounded text-xs",children:"X-API-Key"},void 0,!1,void 0,this)," header."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),!B&&!R&&q.jsxDEV("button",{onClick:()=>{M(!0),O(null)},className:"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition flex-shrink-0",children:[q.jsxDEV(n,{className:"w-4 h-4"},void 0,!1,void 0,this),"New Key"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),R&&q.jsxDEV("div",{className:"bg-green-500/10 border border-green-500/30 rounded-lg p-4 mb-6",children:[q.jsxDEV("div",{className:"flex items-center gap-2 text-green-400 mb-2",children:[q.jsxDEV(g,{className:"w-5 h-5"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"font-medium",children:"API key created"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#888] mb-3",children:"Copy this key now. You won't be able to see it again."},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2",children:[q.jsxDEV("code",{className:"flex-1 bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#e0e0e0] break-all select-all",children:R},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:h,className:"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm flex-shrink-0",children:w?"Copied!":"Copy"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>{X(null),M(!1)},className:"mt-3 text-sm text-[#666] hover:text-[#888]",children:"Done"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B&&!R&&q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 mb-6",children:[q.jsxDEV("h3",{className:"font-medium mb-4",children:"Create new API key"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"space-y-4 max-w-md",children:[q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Name"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"text",value:Q,onChange:(Y)=>L(Y.target.value),placeholder:"e.g. CI Pipeline, My Script",autoFocus:!0,className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Expiration"},void 0,!1,void 0,this),q.jsxDEV("select",{value:_,onChange:(Y)=>N(Y.target.value),className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]",children:[q.jsxDEV("option",{value:"30",children:"30 days"},void 0,!1,void 0,this),q.jsxDEV("option",{value:"90",children:"90 days"},void 0,!1,void 0,this),q.jsxDEV("option",{value:"180",children:"180 days"},void 0,!1,void 0,this),q.jsxDEV("option",{value:"365",children:"1 year"},void 0,!1,void 0,this),q.jsxDEV("option",{value:"",children:"No expiration"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),I&&q.jsxDEV("p",{className:"text-red-400 text-sm",children:I},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex gap-2",children:[q.jsxDEV("button",{onClick:()=>{M(!1),O(null),L("")},className:"flex-1 px-3 py-2 border border-[#333] rounded text-sm hover:border-[#666]",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:f,disabled:J||!Q.trim(),className:"flex-1 px-3 py-2 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50",children:J?"Creating...":"Create Key"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z.length===0?q.jsxDEV("div",{className:"text-center py-12 text-[#666]",children:[q.jsxDEV("p",{className:"text-lg mb-2",children:"No API keys yet"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm",children:"Create an API key to access apteva programmatically."},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"space-y-3",children:Z.map((Y)=>q.jsxDEV("div",{className:`bg-[#111] border rounded-lg p-4 flex items-center gap-4 ${!Y.is_active||G(Y.expires_at)?"border-[#1a1a1a] opacity-60":"border-[#1a1a1a]"}`,children:[q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("div",{className:"flex items-center gap-2 mb-1",children:[q.jsxDEV("h3",{className:"font-medium",children:Y.name},void 0,!1,void 0,this),!Y.is_active&&q.jsxDEV("span",{className:"text-xs text-red-400 bg-red-500/10 px-2 py-0.5 rounded",children:"Revoked"},void 0,!1,void 0,this),Y.is_active&&G(Y.expires_at)&&q.jsxDEV("span",{className:"text-xs text-yellow-400 bg-yellow-500/10 px-2 py-0.5 rounded",children:"Expired"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-3 text-sm text-[#666]",children:[q.jsxDEV("code",{className:"font-mono text-xs bg-[#0a0a0a] px-2 py-0.5 rounded",children:[Y.prefix,"..."]},void 0,!0,void 0,this),q.jsxDEV("span",{children:["Created ",C(Y.created_at)]},void 0,!0,void 0,this),Y.expires_at&&q.jsxDEV("span",{children:["Expires ",C(Y.expires_at)]},void 0,!0,void 0,this),Y.last_used_at&&q.jsxDEV("span",{children:["Last used ",C(Y.last_used_at)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y.is_active&&q.jsxDEV("button",{onClick:()=>u(Y.id,Y.name),className:"text-sm text-red-400 hover:text-red-300 px-2 py-1 flex-shrink-0",children:"Delete"},void 0,!1,void 0,this)]},Y.id,!0,void 0,this))},void 0,!1,void 0,this),Z.length>0&&q.jsxDEV("div",{className:"mt-6 bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:[q.jsxDEV("h3",{className:"font-medium mb-2 text-sm",children:"Usage"},void 0,!1,void 0,this),q.jsxDEV("code",{className:"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-xs text-[#888]",children:'curl -H "X-API-Key: apt_..." http://localhost:4280/api/agents'},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Gq(){let{authFetch:z,user:Z}=v(),[W,B]=H.useState(""),[M,Q]=H.useState(""),[L,_]=H.useState(""),[N,J]=H.useState(!1),[T,I]=H.useState(null),O=async()=>{if(!W||!M||!L){I({type:"error",text:"All fields are required"});return}if(M!==L){I({type:"error",text:"New passwords do not match"});return}if(M.length<8){I({type:"error",text:"Password must be at least 8 characters"});return}J(!0),I(null);try{let R=await z("/api/auth/password",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentPassword:W,newPassword:M})}),X=await R.json();if(R.ok)I({type:"success",text:"Password updated successfully"}),B(""),Q(""),_("");else I({type:"error",text:X.error||"Failed to update password"})}catch{I({type:"error",text:"Failed to update password"})}J(!1)};return q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"Account Settings"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:"Manage your account and security."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 mb-6",children:[q.jsxDEV("h3",{className:"font-medium mb-3",children:"Profile"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"space-y-2 text-sm",children:[q.jsxDEV("div",{className:"flex justify-between",children:[q.jsxDEV("span",{className:"text-[#666]",children:"Username"},void 0,!1,void 0,this),q.jsxDEV("span",{children:Z.username},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z.email&&q.jsxDEV("div",{className:"flex justify-between",children:[q.jsxDEV("span",{className:"text-[#666]",children:"Email"},void 0,!1,void 0,this),q.jsxDEV("span",{children:Z.email},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex justify-between",children:[q.jsxDEV("span",{className:"text-[#666]",children:"Role"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"capitalize",children:Z.role},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:[q.jsxDEV("h3",{className:"font-medium mb-4",children:"Change Password"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"space-y-4 max-w-md",children:[q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Current Password"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"password",value:W,onChange:(R)=>B(R.target.value),className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"New Password"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"password",value:M,onChange:(R)=>Q(R.target.value),className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Confirm New Password"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"password",value:L,onChange:(R)=>_(R.target.value),className:"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T&&q.jsxDEV("div",{className:`p-3 rounded text-sm ${T.type==="success"?"bg-green-500/10 text-green-400 border border-green-500/30":"bg-red-500/10 text-red-400 border border-red-500/30"}`,children:T.text},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:O,disabled:N||!W||!M||!L,className:"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 disabled:cursor-not-allowed text-black rounded text-sm font-medium transition",children:N?"Updating...":"Update Password"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Wq(){let{authFetch:z}=v(),[Z,W]=H.useState(!1),[B,M]=H.useState(null),[Q,L]=H.useState(null),{confirm:_,ConfirmDialog:N}=V(),J=async()=>{try{let O=await(await z("/api/telemetry/stats")).json();L(O.stats?.total_events||0)}catch{L(null)}};H.useEffect(()=>{J()},[]);let T=async()=>{if(!await _("Are you sure you want to delete all telemetry data? This cannot be undone.",{confirmText:"Clear All",title:"Clear Telemetry Data"}))return;W(!0),M(null);try{let O=await z("/api/telemetry/clear",{method:"POST"}),R=await O.json();if(O.ok)M({type:"success",text:`Cleared ${R.deleted||0} telemetry events.`}),L(0);else M({type:"error",text:R.error||"Failed to clear telemetry"})}catch{M({type:"error",text:"Failed to clear telemetry"})}W(!1)};return q.jsxDEV(q.Fragment,{children:[N,q.jsxDEV("div",{className:"max-w-4xl w-full",children:[q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"Data Management"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[#666]",children:"Manage stored data and telemetry."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:[q.jsxDEV("h3",{className:"font-medium mb-2",children:"Telemetry Data"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666] mb-4",children:Q!==null?`${Q.toLocaleString()} events stored`:"Loading..."},void 0,!1,void 0,this),B&&q.jsxDEV("div",{className:`mb-4 p-3 rounded text-sm ${B.type==="success"?"bg-green-500/10 text-green-400 border border-green-500/30":"bg-red-500/10 text-red-400 border border-red-500/30"}`,children:B.text},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:T,disabled:Z||Q===0,className:"px-4 py-2 bg-red-500/20 text-red-400 hover:bg-red-500/30 disabled:opacity-50 disabled:cursor-not-allowed rounded text-sm font-medium transition",children:Z?"Clearing...":"Clear All Telemetry"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Jq(){let{authFetch:z}=v(),[Z,W]=H.useState([]),[B,M]=H.useState([]),[Q,L]=H.useState(!0),[_,N]=H.useState(!1),[J,T]=H.useState({name:"",agent_id:"",botToken:""}),[I,O]=H.useState(!1),[R,X]=H.useState(null),{confirm:w,ConfirmDialog:U}=V(),F=async()=>{try{let Y=await(await z("/api/channels")).json();W(Y.channels||[])}catch{}finally{L(!1)}},b=async()=>{try{let Y=await(await z("/api/agents")).json();M((Y.agents||[]).map((P)=>({id:P.id,name:P.name,status:P.status})))}catch{}};H.useEffect(()=>{F(),b()},[]);let k=async()=>{if(!J.name||!J.agent_id||!J.botToken)return;O(!0),X(null);try{let G=await z("/api/channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"telegram",name:J.name,agent_id:J.agent_id,config:{botToken:J.botToken}})});if(!G.ok){let Y=await G.json();X(Y.error||"Failed to create channel")}else T({name:"",agent_id:"",botToken:""}),N(!1),await F()}catch(G){X(G.message)}finally{O(!1)}},f=async(G)=>{let Y=G.status==="running"?"stop":"start";try{let P=await z(`/api/channels/${G.id}/${Y}`,{method:"POST"});if(!P.ok){let K=await P.json();X(K.error||`Failed to ${Y} channel`)}await F()}catch{X(`Failed to ${Y} channel`)}},u=async(G)=>{if(!await w(`Delete channel "${G.name}"?`,{confirmText:"Delete",title:"Delete Channel"}))return;try{await z(`/api/channels/${G.id}`,{method:"DELETE"}),await F()}catch{}},h={running:"bg-green-500/20 text-green-400",stopped:"bg-[#333] text-[#666]",error:"bg-red-500/20 text-red-400"},C=(G)=>{return B.find((Y)=>Y.id===G)?.name||G};return q.jsxDEV(q.Fragment,{children:[U,q.jsxDEV("div",{className:"max-w-2xl",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-6",children:[q.jsxDEV("div",{children:[q.jsxDEV("h2",{className:"text-xl font-semibold mb-1",children:"Channels"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:"Connect agents to external messaging platforms"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:()=>N(!_),className:"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-3 py-1.5 rounded text-sm font-medium transition",children:[q.jsxDEV(n,{},void 0,!1,void 0,this)," Add Channel"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),R&&q.jsxDEV("div",{className:"mb-4 bg-red-500/10 text-red-400 border border-red-500/30 px-3 py-2 rounded text-sm flex items-center justify-between",children:[q.jsxDEV("span",{children:R},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>X(null),className:"text-red-400 hover:text-red-300 ml-2",children:q.jsxDEV(o,{},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_&&q.jsxDEV("div",{className:"mb-6 bg-[#111] border border-[#1a1a1a] rounded-lg p-4 space-y-3",children:[q.jsxDEV("h3",{className:"text-sm font-medium text-[#888] mb-2",children:"New Telegram Channel"},void 0,!1,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#666] mb-1",children:"Channel Name"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"text",value:J.name,onChange:(G)=>T((Y)=>({...Y,name:G.target.value})),placeholder:"e.g. My Telegram Bot",className:"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#666] mb-1",children:"Agent"},void 0,!1,void 0,this),q.jsxDEV(d,{value:J.agent_id,options:B.map((G)=>({value:G.id,label:G.name})),onChange:(G)=>T((Y)=>({...Y,agent_id:G})),placeholder:"Select an agent..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#666] mb-1",children:"Bot Token"},void 0,!1,void 0,this),q.jsxDEV("input",{type:"password",value:J.botToken,onChange:(G)=>T((Y)=>({...Y,botToken:G.target.value})),placeholder:"From @BotFather on Telegram",className:"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#555] mt-1",children:["Create a bot via ",q.jsxDEV("a",{href:"https://t.me/BotFather",target:"_blank",className:"text-[#f97316] hover:underline",children:"@BotFather"},void 0,!1,void 0,this)," on Telegram to get a token."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex gap-2 pt-1",children:[q.jsxDEV("button",{onClick:k,disabled:I||!J.name||!J.agent_id||!J.botToken,className:"bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-4 py-1.5 rounded text-sm font-medium transition",children:I?"Creating...":"Create"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>{N(!1),T({name:"",agent_id:"",botToken:""})},className:"border border-[#333] hover:border-[#444] px-4 py-1.5 rounded text-sm transition",children:"Cancel"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q?q.jsxDEV("p",{className:"text-[#666] text-sm",children:"Loading channels..."},void 0,!1,void 0,this):Z.length===0?q.jsxDEV("div",{className:"text-center py-12 text-[#666]",children:[q.jsxDEV("p",{className:"text-lg mb-2",children:"No channels configured"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm",children:"Add a Telegram channel to let users message your agents directly."},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"space-y-3",children:Z.map((G)=>q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:q.jsxDEV("div",{className:"flex items-start justify-between",children:[q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("div",{className:"flex items-center gap-2 mb-1",children:[q.jsxDEV("h3",{className:"font-medium",children:G.name},void 0,!1,void 0,this),q.jsxDEV("span",{className:`px-2 py-0.5 rounded text-xs font-medium ${h[G.status]||h.stopped}`,children:G.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666]",children:[G.type==="telegram"?"Telegram":G.type," → ",C(G.agent_id)]},void 0,!0,void 0,this),G.status==="error"&&G.error&&q.jsxDEV("p",{className:"text-xs text-red-400 mt-1",children:G.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2 ml-4",children:[q.jsxDEV("button",{onClick:()=>f(G),className:`px-3 py-1 rounded text-xs font-medium transition ${G.status==="running"?"bg-[#f97316]/20 text-[#f97316] hover:bg-[#f97316]/30":"bg-[#3b82f6]/20 text-[#3b82f6] hover:bg-[#3b82f6]/30"}`,children:G.status==="running"?"Stop":"Start"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>u(G),className:"text-[#666] hover:text-red-400 transition text-sm",children:"×"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function _q(){let{authFetch:z}=v(),[Z,W]=H.useState([]),[B,M]=H.useState(""),[Q,L]=H.useState(""),[_,N]=H.useState(""),[J,T]=H.useState("unknown"),[I,O]=H.useState(!0),[R,X]=H.useState(!1),[w,U]=H.useState(null),[F,b]=H.useState(!1),[k,f]=H.useState({provider:"",model:"",systemPrompt:""});H.useEffect(()=>{(async()=>{try{let[y,p]=await Promise.all([z("/api/meta-agent/status"),z("/api/providers")]),$=await y.json(),l=await p.json();if(W((l.providers||[]).filter((m)=>m.type==="llm"&&m.hasKey)),$.agent){let m=$.agent;M(m.provider||""),L(m.model||""),N(m.systemPrompt||""),T(m.status||"stopped"),f({provider:m.provider||"",model:m.model||"",systemPrompt:m.systemPrompt||""})}}catch{U({type:"error",text:"Failed to load assistant config"})}finally{O(!1)}})()},[z]);let h=Z.find((K)=>K.id===B)?.models||[],C=(K)=>{M(K);let y=Z.find(($)=>$.id===K),p=y?.models.find(($)=>$.recommended)?.value||y?.models[0]?.value||"";L(p)},G=B!==k.provider||Q!==k.model||_!==k.systemPrompt,Y=async()=>{X(!0),U(null);try{let K=await z("/api/agents/apteva-assistant",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:B,model:Q,systemPrompt:_})});if(K.ok)f({provider:B,model:Q,systemPrompt:_}),U({type:"success",text:"Assistant settings saved"}),setTimeout(()=>U(null),3000);else{let y=await K.json().catch(()=>({}));U({type:"error",text:y.error||"Failed to save"})}}catch{U({type:"error",text:"Failed to save settings"})}finally{X(!1)}},P=async()=>{b(!0),U(null);try{let y=await z(J==="running"?"/api/meta-agent/stop":"/api/meta-agent/start",{method:"POST"});if(y.ok)T(J==="running"?"stopped":"running");else{let p=await y.json().catch(()=>({}));U({type:"error",text:p.error||"Failed to toggle assistant"})}}catch{U({type:"error",text:"Failed to toggle assistant"})}finally{b(!1)}};if(I)return q.jsxDEV("div",{className:"text-[#666]",children:"Loading assistant settings..."},void 0,!1,void 0,this);return q.jsxDEV("div",{className:"max-w-2xl",children:[q.jsxDEV("h2",{className:"text-lg font-medium mb-1",children:"Apteva Assistant"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[#666] mb-6",children:"Configure the built-in AI assistant that manages your agents and platform."},void 0,!1,void 0,this),w&&q.jsxDEV("div",{className:`mb-4 px-3 py-2 rounded text-sm ${w.type==="success"?"bg-green-500/10 text-green-400":"bg-red-500/10 text-red-400"}`,children:w.text},void 0,!1,void 0,this),q.jsxDEV("div",{className:"mb-6 flex items-center gap-3",children:[q.jsxDEV("span",{className:"text-sm text-[#666]",children:"Status:"},void 0,!1,void 0,this),q.jsxDEV("span",{className:`px-2 py-1 rounded text-xs font-medium ${J==="running"?"bg-[#3b82f6]/20 text-[#3b82f6]":"bg-[#333] text-[#666]"}`,children:J},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:P,disabled:F,className:`px-3 py-1.5 rounded text-sm font-medium transition ${J==="running"?"bg-[#f97316]/20 text-[#f97316] hover:bg-[#f97316]/30":"bg-[#3b82f6]/20 text-[#3b82f6] hover:bg-[#3b82f6]/30"} disabled:opacity-50`,children:F?"...":J==="running"?"Stop":"Start"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mb-4",children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Provider"},void 0,!1,void 0,this),q.jsxDEV(d,{value:B,onChange:C,options:Z.map((K)=>({value:K.id,label:K.name})),placeholder:"Select provider..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mb-4",children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"Model"},void 0,!1,void 0,this),q.jsxDEV(d,{value:Q,onChange:L,options:h.map((K)=>({value:K.value,label:K.label,recommended:K.recommended})),placeholder:"Select model..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"mb-6",children:[q.jsxDEV("label",{className:"block text-sm text-[#666] mb-1",children:"System Prompt"},void 0,!1,void 0,this),q.jsxDEV("textarea",{value:_,onChange:(K)=>N(K.target.value),rows:12,className:"w-full bg-[#111] border border-[#1a1a1a] rounded px-3 py-2 text-sm font-mono focus:outline-none focus:border-[#f97316] resize-y"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("button",{onClick:Y,disabled:!G||R,className:"bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 disabled:cursor-not-allowed text-black px-4 py-2 rounded font-medium transition",children:R?"Saving...":"Save Changes"},void 0,!1,void 0,this),J==="running"&&G&&q.jsxDEV("p",{className:"text-xs text-[#666] mt-2",children:"Changes will be applied to the running assistant"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}
|
|
2
|
+
export{Oq as c};
|
|
3
|
+
|
|
4
|
+
//# debugId=A7AC98F21789CBAB64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/web/components/settings/SettingsPage.tsx"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import React, { useState, useEffect } from \"react\";\nimport { CheckIcon, CloseIcon, PlusIcon } from \"../common/Icons\";\nimport { Modal, useConfirm } from \"../common/Modal\";\nimport { Select } from \"../common/Select\";\nimport { useProjects, useAuth, type Project } from \"../../context\";\nimport type { Provider } from \"../../types\";\n\ntype SettingsTab = \"general\" | \"providers\" | \"projects\" | \"channels\" | \"api-keys\" | \"account\" | \"updates\" | \"data\" | \"assistant\";\n\nexport function SettingsPage() {\n const { projectsEnabled, metaAgentEnabled } = useProjects();\n const [activeTab, setActiveTab] = useState<SettingsTab>(\"general\");\n\n const tabs: { key: SettingsTab; label: string }[] = [\n { key: \"general\", label: \"General\" },\n { key: \"providers\", label: \"Providers\" },\n ...(projectsEnabled ? [{ key: \"projects\" as SettingsTab, label: \"Projects\" }] : []),\n ...(metaAgentEnabled ? [{ key: \"assistant\" as SettingsTab, label: \"Assistant\" }] : []),\n { key: \"channels\", label: \"Channels\" },\n { key: \"api-keys\", label: \"API Keys\" },\n { key: \"account\", label: \"Account\" },\n { key: \"updates\", label: \"Updates\" },\n { key: \"data\", label: \"Data\" },\n ];\n\n return (\n <div className=\"flex-1 flex flex-col md:flex-row overflow-hidden\">\n {/* Mobile: Horizontal scrolling tabs */}\n <div className=\"md:hidden border-b border-[#1a1a1a] bg-[#0a0a0a]\">\n <div className=\"flex overflow-x-auto\" style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}>\n {tabs.map(tab => (\n <button\n key={tab.key}\n onClick={() => setActiveTab(tab.key)}\n className={`flex-shrink-0 px-4 py-3 text-sm font-medium border-b-2 transition ${\n activeTab === tab.key\n ? \"border-[#f97316] text-[#f97316]\"\n : \"border-transparent text-[#666] hover:text-[#888]\"\n }`}\n >\n {tab.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Desktop: Settings Sidebar */}\n <div className=\"hidden md:block w-48 border-r border-[#1a1a1a] p-4 flex-shrink-0\">\n <h2 className=\"text-sm font-medium text-[#666] uppercase tracking-wider mb-3\">Settings</h2>\n <nav className=\"space-y-1\">\n {tabs.map(tab => (\n <SettingsNavItem\n key={tab.key}\n label={tab.label}\n active={activeTab === tab.key}\n onClick={() => setActiveTab(tab.key)}\n />\n ))}\n </nav>\n </div>\n\n {/* Settings Content */}\n <div className=\"flex-1 overflow-auto p-4 md:p-6\">\n {activeTab === \"general\" && <GeneralSettings />}\n {activeTab === \"providers\" && <ProvidersSettings />}\n {activeTab === \"projects\" && projectsEnabled && <ProjectsSettings />}\n {activeTab === \"channels\" && <ChannelsSettings />}\n {activeTab === \"api-keys\" && <ApiKeysSettings />}\n {activeTab === \"account\" && <AccountSettings />}\n {activeTab === \"updates\" && <UpdatesSettings />}\n {activeTab === \"data\" && <DataSettings />}\n {activeTab === \"assistant\" && metaAgentEnabled && <AssistantSettings />}\n </div>\n </div>\n );\n}\n\nfunction SettingsNavItem({\n label,\n active,\n onClick\n}: {\n label: string;\n active: boolean;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n className={`w-full text-left px-3 py-2 rounded text-sm transition ${\n active\n ? \"bg-[#1a1a1a] text-[#e0e0e0]\"\n : \"text-[#666] hover:bg-[#111] hover:text-[#888]\"\n }`}\n >\n {label}\n </button>\n );\n}\n\nfunction GeneralSettings() {\n const { authFetch } = useAuth();\n const [instanceUrl, setInstanceUrl] = useState(\"\");\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [message, setMessage] = useState<{ type: \"success\" | \"error\"; text: string } | null>(null);\n\n useEffect(() => {\n const fetch = async () => {\n try {\n const res = await authFetch(\"/api/settings/instance-url\");\n const data = await res.json();\n setInstanceUrl(data.instance_url || \"\");\n } catch {\n // ignore\n }\n setLoading(false);\n };\n fetch();\n }, []);\n\n const handleSave = async () => {\n setSaving(true);\n setMessage(null);\n try {\n const res = await authFetch(\"/api/settings/instance-url\", {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ instance_url: instanceUrl }),\n });\n const data = await res.json();\n if (res.ok) {\n setInstanceUrl(data.instance_url || \"\");\n setMessage({ type: \"success\", text: \"Instance URL saved\" });\n } else {\n setMessage({ type: \"error\", text: data.error || \"Failed to save\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to save\" });\n }\n setSaving(false);\n };\n\n return (\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold mb-1\">General</h1>\n <p className=\"text-[#666]\">Instance configuration.</p>\n </div>\n\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <h3 className=\"font-medium mb-2\">Instance URL</h3>\n <p className=\"text-sm text-[#666] mb-4\">\n The public HTTPS URL for this instance. Used for webhook callbacks from external services like Composio.\n </p>\n\n {loading ? (\n <div className=\"text-[#666] text-sm\">Loading...</div>\n ) : (\n <div className=\"space-y-3 max-w-lg\">\n <input\n type=\"text\"\n value={instanceUrl}\n onChange={e => setInstanceUrl(e.target.value)}\n placeholder=\"https://your-domain.com\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316] font-mono text-sm\"\n />\n\n {message && (\n <div className={`p-3 rounded text-sm ${\n message.type === \"success\"\n ? \"bg-green-500/10 text-green-400 border border-green-500/30\"\n : \"bg-red-500/10 text-red-400 border border-red-500/30\"\n }`}>\n {message.text}\n </div>\n )}\n\n <button\n onClick={handleSave}\n disabled={saving}\n className=\"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black rounded text-sm font-medium transition\"\n >\n {saving ? \"Saving...\" : \"Save\"}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction ProvidersSettings() {\n const { authFetch } = useAuth();\n const { projects, projectsEnabled } = useProjects();\n const [providers, setProviders] = useState<Provider[]>([]);\n const [selectedProvider, setSelectedProvider] = useState<string | null>(null);\n const [apiKey, setApiKey] = useState(\"\");\n const [extraField, setExtraField] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [testing, setTesting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState<string | null>(null);\n const { confirm, ConfirmDialog } = useConfirm();\n\n const fetchProviders = async () => {\n const res = await authFetch(\"/api/providers\");\n const data = await res.json();\n setProviders(data.providers || []);\n };\n\n useEffect(() => {\n fetchProviders();\n }, []);\n\n const saveKey = async () => {\n if (!selectedProvider || !apiKey) return;\n setSaving(true);\n setError(null);\n setSuccess(null);\n\n // For multi-field providers, combine into JSON\n let keyToSave = apiKey;\n if (selectedProvider === \"browserbase\" && extraField) {\n keyToSave = JSON.stringify({ api_key: apiKey, project_id: extraField });\n }\n\n try {\n setTesting(true);\n const testRes = await authFetch(`/api/keys/${selectedProvider}/test`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ key: keyToSave }),\n });\n const testData = await testRes.json();\n setTesting(false);\n\n if (!testData.valid) {\n setError(testData.error || \"API key is invalid\");\n setSaving(false);\n return;\n }\n\n const saveRes = await authFetch(`/api/keys/${selectedProvider}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ key: keyToSave }),\n });\n\n const saveData = await saveRes.json();\n if (!saveRes.ok) {\n setError(saveData.error || \"Failed to save key\");\n } else {\n // Build success message including agent restart info\n let msg = \"API key saved!\";\n if (saveData.restartedAgents && saveData.restartedAgents.length > 0) {\n const successCount = saveData.restartedAgents.filter((a: { success: boolean }) => a.success).length;\n const failCount = saveData.restartedAgents.length - successCount;\n if (failCount === 0) {\n msg += ` Restarted ${successCount} agent${successCount > 1 ? 's' : ''} with new key.`;\n } else {\n msg += ` Restarted ${successCount}/${saveData.restartedAgents.length} agents.`;\n }\n }\n setSuccess(msg);\n setApiKey(\"\");\n setExtraField(\"\");\n setSelectedProvider(null);\n fetchProviders();\n }\n } catch (e) {\n setError(\"Failed to save key\");\n }\n setSaving(false);\n };\n\n const deleteKey = async (providerId: string) => {\n const confirmed = await confirm(\"Are you sure you want to remove this API key?\", { confirmText: \"Remove\", title: \"Remove API Key\" });\n if (!confirmed) return;\n await authFetch(`/api/keys/${providerId}`, { method: \"DELETE\" });\n fetchProviders();\n };\n\n const llmProviders = providers.filter(p => p.type === \"llm\");\n const integrations = providers.filter(p => p.type === \"integration\");\n const browserProviders = providers.filter(p => p.type === \"browser\");\n const llmConfiguredCount = llmProviders.filter(p => p.hasKey).length;\n const intConfiguredCount = integrations.filter(p => p.hasKey).length;\n const browserConfiguredCount = browserProviders.filter(p => p.hasKey).length;\n\n // Auto-dismiss success message after 5 seconds\n useEffect(() => {\n if (success && !selectedProvider) {\n const timer = setTimeout(() => setSuccess(null), 5000);\n return () => clearTimeout(timer);\n }\n }, [success, selectedProvider]);\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"space-y-10\">\n {/* Global Success Banner */}\n {success && !selectedProvider && (\n <div className=\"bg-green-500/10 border border-green-500/30 rounded-lg p-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-green-400\">\n <CheckIcon className=\"w-5 h-5\" />\n <span>{success}</span>\n </div>\n <button\n onClick={() => setSuccess(null)}\n className=\"text-green-400 hover:text-green-300\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )}\n\n {/* AI Providers Section */}\n <div>\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold mb-1\">AI Providers</h1>\n <p className=\"text-[#666]\">\n Manage your API keys for AI providers. {llmConfiguredCount} of {llmProviders.length} configured.\n </p>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {llmProviders.map(provider => (\n <ProviderKeyCard\n key={provider.id}\n provider={provider}\n isEditing={selectedProvider === provider.id}\n apiKey={apiKey}\n saving={saving}\n testing={testing}\n error={selectedProvider === provider.id ? error : null}\n success={selectedProvider === provider.id ? success : null}\n onStartEdit={() => {\n setSelectedProvider(provider.id);\n setError(null);\n setSuccess(null);\n }}\n onCancelEdit={() => {\n setSelectedProvider(null);\n setApiKey(\"\");\n setError(null);\n }}\n onApiKeyChange={setApiKey}\n onSave={saveKey}\n onDelete={() => deleteKey(provider.id)}\n />\n ))}\n </div>\n </div>\n\n {/* MCP Integrations Section */}\n <div>\n <div className=\"mb-6\">\n <h2 className=\"text-xl font-semibold mb-1\">MCP Integrations</h2>\n <p className=\"text-[#666]\">\n Connect to MCP gateways for tool integrations. {intConfiguredCount} of {integrations.length} configured.\n </p>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {integrations.map(provider => (\n <IntegrationKeyCard\n key={provider.id}\n provider={provider}\n isEditing={selectedProvider === provider.id}\n apiKey={apiKey}\n saving={saving}\n testing={testing}\n error={selectedProvider === provider.id ? error : null}\n success={selectedProvider === provider.id ? success : null}\n onStartEdit={() => {\n setSelectedProvider(provider.id);\n setError(null);\n setSuccess(null);\n }}\n onCancelEdit={() => {\n setSelectedProvider(null);\n setApiKey(\"\");\n setError(null);\n }}\n onApiKeyChange={setApiKey}\n onSave={saveKey}\n onDelete={() => deleteKey(provider.id)}\n projectsEnabled={projectsEnabled}\n projects={projects}\n onRefresh={fetchProviders}\n />\n ))}\n </div>\n </div>\n\n {/* Browser Providers Section */}\n <div>\n <div className=\"mb-6\">\n <h2 className=\"text-xl font-semibold mb-1\">Browser Providers</h2>\n <p className=\"text-[#666]\">\n Configure browser environments for operator mode (computer use). {browserConfiguredCount} of {browserProviders.length} configured.\n </p>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {browserProviders.map(provider => (\n <ProviderKeyCard\n key={provider.id}\n provider={provider}\n isEditing={selectedProvider === provider.id}\n apiKey={apiKey}\n saving={saving}\n testing={testing}\n error={selectedProvider === provider.id ? error : null}\n success={selectedProvider === provider.id ? success : null}\n onStartEdit={() => {\n setSelectedProvider(provider.id);\n setError(null);\n setSuccess(null);\n }}\n onCancelEdit={() => {\n setSelectedProvider(null);\n setApiKey(\"\");\n setExtraField(\"\");\n setError(null);\n }}\n onApiKeyChange={setApiKey}\n onSave={saveKey}\n onDelete={() => deleteKey(provider.id)}\n extraField={extraField}\n onExtraFieldChange={setExtraField}\n />\n ))}\n </div>\n </div>\n </div>\n </>\n );\n}\n\nconst DEFAULT_PROJECT_COLORS = [\n \"#f97316\", // orange\n \"#6366f1\", // indigo\n \"#22c55e\", // green\n \"#ef4444\", // red\n \"#3b82f6\", // blue\n \"#a855f7\", // purple\n \"#14b8a6\", // teal\n \"#f59e0b\", // amber\n];\n\nfunction ProjectsSettings() {\n const { projects, createProject, updateProject, deleteProject } = useProjects();\n const [showModal, setShowModal] = useState(false);\n const [editingProject, setEditingProject] = useState<Project | null>(null);\n const { confirm, ConfirmDialog } = useConfirm();\n\n const handleDelete = async (id: string) => {\n const confirmed = await confirm(\"Are you sure you want to delete this project? Agents in this project will become unassigned.\", { confirmText: \"Delete\", title: \"Delete Project\" });\n if (!confirmed) return;\n await deleteProject(id);\n };\n\n const openCreate = () => {\n setEditingProject(null);\n setShowModal(true);\n };\n\n const openEdit = (project: Project) => {\n setEditingProject(project);\n setShowModal(true);\n };\n\n const closeModal = () => {\n setShowModal(false);\n setEditingProject(null);\n };\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6 flex items-center justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-semibold mb-1\">Projects</h1>\n <p className=\"text-[#666]\">\n Organize agents into projects for better management.\n </p>\n </div>\n <button\n onClick={openCreate}\n className=\"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition flex-shrink-0\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n New Project\n </button>\n </div>\n\n {/* Project List */}\n {projects.length === 0 ? (\n <div className=\"text-center py-12 text-[#666]\">\n <p className=\"text-lg mb-2\">No projects yet</p>\n <p className=\"text-sm\">Create a project to organize your agents.</p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {projects.map(project => (\n <div\n key={project.id}\n className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 flex items-center gap-4\"\n >\n <div\n className=\"w-4 h-4 rounded-full flex-shrink-0\"\n style={{ backgroundColor: project.color }}\n />\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-medium\">{project.name}</h3>\n {project.description && (\n <p className=\"text-sm text-[#666] truncate\">{project.description}</p>\n )}\n <p className=\"text-xs text-[#666] mt-1\">\n {project.agentCount} agent{project.agentCount !== 1 ? \"s\" : \"\"}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => openEdit(project)}\n className=\"text-sm text-[#888] hover:text-[#e0e0e0] px-2 py-1\"\n >\n Edit\n </button>\n <button\n onClick={() => handleDelete(project.id)}\n className=\"text-sm text-red-400 hover:text-red-300 px-2 py-1\"\n >\n Delete\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Project Modal */}\n {showModal && (\n <ProjectModal\n project={editingProject}\n onSave={async (data) => {\n if (editingProject) {\n const result = await updateProject(editingProject.id, data);\n if (result) closeModal();\n return !!result;\n } else {\n const result = await createProject(data);\n if (result) closeModal();\n return !!result;\n }\n }}\n onClose={closeModal}\n />\n )}\n </div>\n </>\n );\n}\n\ninterface ProjectModalProps {\n project: Project | null;\n onSave: (data: { name: string; description?: string; color: string }) => Promise<boolean>;\n onClose: () => void;\n}\n\nfunction ProjectModal({ project, onSave, onClose }: ProjectModalProps) {\n const [name, setName] = useState(project?.name || \"\");\n const [description, setDescription] = useState(project?.description || \"\");\n const [color, setColor] = useState(\n project?.color || DEFAULT_PROJECT_COLORS[Math.floor(Math.random() * DEFAULT_PROJECT_COLORS.length)]\n );\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleSubmit = async () => {\n if (!name.trim()) {\n setError(\"Name is required\");\n return;\n }\n setSaving(true);\n setError(null);\n const success = await onSave({ name, description: description || undefined, color });\n setSaving(false);\n if (!success) {\n setError(project ? \"Failed to update project\" : \"Failed to create project\");\n }\n };\n\n return (\n <Modal onClose={onClose}>\n <h2 className=\"text-xl font-semibold mb-6\">{project ? \"Edit Project\" : \"Create New Project\"}</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Name</label>\n <input\n type=\"text\"\n value={name}\n onChange={e => setName(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n placeholder=\"My Project\"\n autoFocus\n />\n </div>\n\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Description (optional)</label>\n <input\n type=\"text\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n placeholder=\"A short description\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Color</label>\n <div className=\"flex gap-3 flex-wrap\">\n {DEFAULT_PROJECT_COLORS.map(c => (\n <button\n key={c}\n type=\"button\"\n onClick={() => setColor(c)}\n className={`w-10 h-10 rounded-full transition ${\n color === c ? \"ring-2 ring-white ring-offset-2 ring-offset-[#111]\" : \"hover:scale-110\"\n }`}\n style={{ backgroundColor: c }}\n />\n ))}\n </div>\n </div>\n\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n </div>\n\n <div className=\"flex gap-3 mt-6\">\n <button\n onClick={onClose}\n className=\"flex-1 border border-[#333] hover:border-[#f97316] hover:text-[#f97316] px-4 py-2 rounded font-medium transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n disabled={saving || !name.trim()}\n className=\"flex-1 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition\"\n >\n {saving ? \"Saving...\" : project ? \"Update\" : \"Create\"}\n </button>\n </div>\n </Modal>\n );\n}\n\ninterface ProviderKeyCardProps {\n provider: Provider;\n isEditing: boolean;\n apiKey: string;\n saving: boolean;\n testing: boolean;\n error: string | null;\n success: string | null;\n onStartEdit: () => void;\n onCancelEdit: () => void;\n onApiKeyChange: (key: string) => void;\n onSave: () => void;\n onDelete: () => void;\n extraField?: string;\n onExtraFieldChange?: (val: string) => void;\n}\n\ninterface VersionInfo {\n installed: string | null;\n latest: string | null;\n updateAvailable: boolean;\n lastChecked: string | null;\n}\n\ninterface AllVersionInfo {\n apteva: VersionInfo;\n agent: VersionInfo;\n isDocker?: boolean;\n}\n\nfunction UpdatesSettings() {\n const { authFetch } = useAuth();\n const [versions, setVersions] = useState<AllVersionInfo | null>(null);\n const [checking, setChecking] = useState(false);\n const [updatingAgent, setUpdatingAgent] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [updateSuccess, setUpdateSuccess] = useState<string | null>(null);\n const [copied, setCopied] = useState<string | null>(null);\n\n const checkForUpdates = async () => {\n setChecking(true);\n setError(null);\n try {\n const res = await authFetch(\"/api/version\");\n if (!res.ok) throw new Error(\"Failed to check for updates\");\n const data = await res.json();\n setVersions(data);\n } catch (e) {\n setError(\"Failed to check for updates\");\n }\n setChecking(false);\n };\n\n const updateAgent = async () => {\n setUpdatingAgent(true);\n setError(null);\n setUpdateSuccess(null);\n try {\n const res = await authFetch(\"/api/version/update\", { method: \"POST\" });\n const data = await res.json();\n if (!data.success) {\n setError(data.error || \"Update failed\");\n } else {\n const restartedCount = data.restarted?.length || 0;\n const restartMsg = restartedCount > 0\n ? ` ${restartedCount} running agent${restartedCount > 1 ? 's' : ''} restarted.`\n : '';\n setUpdateSuccess(`Agent binary updated to v${data.version}.${restartMsg}`);\n await checkForUpdates();\n }\n } catch (e) {\n setError(\"Failed to update agent\");\n }\n setUpdatingAgent(false);\n };\n\n useEffect(() => {\n checkForUpdates();\n }, []);\n\n const copyCommand = (cmd: string, id: string) => {\n navigator.clipboard.writeText(cmd);\n setCopied(id);\n setTimeout(() => setCopied(null), 2000);\n };\n\n const hasAnyUpdate = versions?.apteva.updateAvailable || versions?.agent.updateAvailable;\n\n return (\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold mb-1\">Updates</h1>\n <p className=\"text-[#666]\">\n Check for new versions of apteva and the agent binary.\n </p>\n </div>\n\n {checking && !versions ? (\n <div className=\"text-[#666]\">Checking version info...</div>\n ) : error && !versions ? (\n <div className=\"text-red-400\">{error}</div>\n ) : versions?.isDocker ? (\n /* Docker Environment */\n <div className=\"space-y-6\">\n <div className=\"bg-blue-500/10 border border-blue-500/30 rounded-lg p-4\">\n <div className=\"flex items-center gap-2 text-blue-400 mb-2\">\n <svg className=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path d=\"M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.186.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.186.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.186.186 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.186.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.185-.186H5.136a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z\"/>\n </svg>\n <span className=\"font-medium\">Docker Environment</span>\n </div>\n <p className=\"text-sm text-[#888]\">\n Updates are automatic when you pull a new image version.\n </p>\n </div>\n\n {/* Current Version */}\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-5\">\n <div className=\"flex items-center justify-between mb-4\">\n <div>\n <h3 className=\"font-medium text-lg\">Current Version</h3>\n <p className=\"text-sm text-[#666]\">apteva + agent binary</p>\n </div>\n <div className=\"text-right\">\n <div className=\"text-xl font-mono\">v{versions.apteva.installed || \"?\"}</div>\n </div>\n </div>\n\n {hasAnyUpdate ? (\n <div className=\"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4\">\n <p className=\"text-sm text-[#888] mb-3\">\n A newer version (v{versions.apteva.latest}) is available. To update:\n </p>\n <div className=\"space-y-2\">\n <code className=\"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]\">\n docker pull apteva/apteva:latest\n </code>\n <code className=\"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]\">\n docker compose up -d\n </code>\n </div>\n <button\n onClick={() => {\n navigator.clipboard.writeText(\"docker pull apteva/apteva:latest && docker compose up -d\");\n setCopied(\"docker\");\n setTimeout(() => setCopied(null), 2000);\n }}\n className=\"mt-3 px-3 py-1.5 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm\"\n >\n {copied === \"docker\" ? \"Copied!\" : \"Copy commands\"}\n </button>\n </div>\n ) : (\n <div className=\"flex items-center gap-2 text-green-400 text-sm\">\n <CheckIcon className=\"w-4 h-4\" />\n Up to date\n </div>\n )}\n </div>\n\n <p className=\"text-xs text-[#555]\">\n Your data is stored in a Docker volume and persists across updates.\n </p>\n </div>\n ) : versions ? (\n /* Non-Docker Environment */\n <div className=\"space-y-6\">\n {updateSuccess && (\n <div className=\"bg-green-500/10 border border-green-500/30 rounded-lg p-4 text-green-400\">\n {updateSuccess}\n </div>\n )}\n\n {error && (\n <div className=\"bg-red-500/10 border border-red-500/30 rounded-lg p-4 text-red-400\">\n {error}\n </div>\n )}\n\n {/* Apteva App Version */}\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-5\">\n <div className=\"flex items-center justify-between mb-4\">\n <div>\n <h3 className=\"font-medium text-lg\">apteva</h3>\n <p className=\"text-sm text-[#666]\">The app you're running</p>\n </div>\n <div className=\"text-right\">\n <div className=\"text-xl font-mono\">v{versions.apteva.installed || \"?\"}</div>\n {versions.apteva.updateAvailable && (\n <div className=\"text-sm text-[#f97316]\">→ v{versions.apteva.latest}</div>\n )}\n </div>\n </div>\n\n {versions.apteva.updateAvailable ? (\n <div className=\"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4\">\n <p className=\"text-sm text-[#888] mb-3\">\n Update by running:\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"flex-1 bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#888]\">\n npx apteva@latest\n </code>\n <button\n onClick={() => copyCommand(\"npx apteva@latest\", \"apteva\")}\n className=\"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm\"\n >\n {copied === \"apteva\" ? \"Copied!\" : \"Copy\"}\n </button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center gap-2 text-green-400 text-sm\">\n <CheckIcon className=\"w-4 h-4\" />\n Up to date\n </div>\n )}\n </div>\n\n {/* Agent Binary Version */}\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-5\">\n <div className=\"flex items-center justify-between mb-4\">\n <div>\n <h3 className=\"font-medium text-lg\">Agent Binary</h3>\n <p className=\"text-sm text-[#666]\">The Go binary that runs agents</p>\n </div>\n <div className=\"text-right\">\n <div className=\"text-xl font-mono\">v{versions.agent.installed || \"?\"}</div>\n {versions.agent.updateAvailable && (\n <div className=\"text-sm text-[#f97316]\">→ v{versions.agent.latest}</div>\n )}\n </div>\n </div>\n\n {versions.agent.updateAvailable ? (\n <div className=\"bg-[#f97316]/10 border border-[#f97316]/30 rounded-lg p-4\">\n <p className=\"text-sm text-[#888] mb-3\">\n A new version is available. Stop all agents before updating.\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={updateAgent}\n disabled={updatingAgent}\n className=\"px-4 py-2 bg-[#f97316] text-black rounded font-medium text-sm disabled:opacity-50\"\n >\n {updatingAgent ? \"Updating...\" : \"Update Agent\"}\n </button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center gap-2 text-green-400 text-sm\">\n <CheckIcon className=\"w-4 h-4\" />\n Up to date\n </div>\n )}\n </div>\n\n {!hasAnyUpdate && !updateSuccess && (\n <div className=\"bg-green-500/10 border border-green-500/30 rounded-lg p-4 flex items-center gap-2 text-green-400\">\n <CheckIcon className=\"w-5 h-5\" />\n Everything is up to date!\n </div>\n )}\n\n <button\n onClick={checkForUpdates}\n disabled={checking}\n className=\"text-sm text-[#666] hover:text-[#888] disabled:opacity-50\"\n >\n {checking ? \"Checking...\" : \"Check for updates\"}\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ProviderKeyCard({\n provider,\n isEditing,\n apiKey,\n saving,\n testing,\n error,\n success,\n onStartEdit,\n onCancelEdit,\n onApiKeyChange,\n onSave,\n onDelete,\n extraField,\n onExtraFieldChange,\n}: ProviderKeyCardProps) {\n const isOllama = provider.id === \"ollama\";\n const isUrlBased = isOllama || provider.id === \"browserengine\" || provider.id === \"chrome\";\n const isBrowser = provider.type === \"browser\";\n const isMultiField = provider.id === \"browserbase\";\n const [ollamaStatus, setOllamaStatus] = React.useState<{ connected: boolean; modelCount?: number } | null>(null);\n\n // Check Ollama status when configured\n React.useEffect(() => {\n if (isOllama && provider.hasKey) {\n fetch(\"/api/providers/ollama/status\")\n .then(res => res.json())\n .then(data => setOllamaStatus({ connected: data.connected, modelCount: data.modelCount }))\n .catch(() => setOllamaStatus({ connected: false }));\n }\n }, [isOllama, provider.hasKey]);\n\n return (\n <div className={`bg-[#111] border rounded-lg p-4 ${\n provider.hasKey ? 'border-green-500/20' : 'border-[#1a1a1a]'\n }`}>\n <div className=\"flex items-start justify-between gap-2 mb-2\">\n <div className=\"min-w-0\">\n <h3 className=\"font-medium\">{provider.name}</h3>\n <p className=\"text-sm text-[#666] truncate\">\n {isBrowser\n ? (provider.description || \"Browser automation\")\n : provider.type === \"integration\"\n ? (provider.description || \"MCP integration\")\n : isOllama\n ? \"Run models locally\"\n : `${provider.models.length} models`}\n </p>\n </div>\n {provider.hasKey ? (\n <span className={`text-xs flex items-center gap-1 px-2 py-1 rounded whitespace-nowrap flex-shrink-0 ${\n isOllama && ollamaStatus\n ? ollamaStatus.connected\n ? \"text-green-400 bg-green-500/10\"\n : \"text-yellow-400 bg-yellow-500/10\"\n : \"text-green-400 bg-green-500/10\"\n }`}>\n {isOllama && ollamaStatus ? (\n ollamaStatus.connected ? (\n <><CheckIcon className=\"w-3 h-3\" />{ollamaStatus.modelCount} models</>\n ) : (\n <>Not running</>\n )\n ) : isUrlBased ? (\n <><CheckIcon className=\"w-3 h-3\" />Configured</>\n ) : (\n <><CheckIcon className=\"w-3 h-3\" />{provider.keyHint}</>\n )}\n </span>\n ) : (\n <span className=\"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded whitespace-nowrap flex-shrink-0\">\n Not configured\n </span>\n )}\n </div>\n\n <div className=\"mt-3 pt-3 border-t border-[#1a1a1a]\">\n {isEditing ? (\n <div className=\"space-y-3\">\n {isMultiField ? (\n <>\n <div>\n <label className=\"block text-xs text-[#888] mb-1\">API Key</label>\n <input\n type=\"password\"\n value={apiKey}\n onChange={e => onApiKeyChange(e.target.value)}\n placeholder={provider.hasKey ? \"Enter new API key...\" : \"Enter API key...\"}\n autoFocus\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-[#888] mb-1\">Project ID</label>\n <input\n type=\"text\"\n value={extraField || \"\"}\n onChange={e => onExtraFieldChange?.(e.target.value)}\n placeholder=\"Enter your Browserbase project ID...\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n </>\n ) : (\n <input\n type={isUrlBased ? \"text\" : \"password\"}\n value={apiKey}\n onChange={e => onApiKeyChange(e.target.value)}\n placeholder={isOllama\n ? \"http://localhost:11434\"\n : provider.id === \"browserengine\"\n ? \"http://localhost:8098\"\n : provider.id === \"chrome\"\n ? \"http://localhost:9222\"\n : provider.hasKey ? \"Enter new API key...\" : \"Enter API key...\"}\n autoFocus\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n )}\n {isUrlBased && (\n <p className=\"text-xs text-[#666]\">\n {isOllama\n ? \"Enter your Ollama server URL. Default is http://localhost:11434\"\n : provider.id === \"browserengine\"\n ? \"Enter your BrowserEngine service URL (e.g., http://localhost:8098)\"\n : \"Enter your Chrome DevTools URL (e.g., http://localhost:9222)\"}\n </p>\n )}\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n {success && <p className=\"text-green-400 text-sm\">{success}</p>}\n <div className=\"flex gap-2\">\n <button\n onClick={onCancelEdit}\n className=\"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]\"\n >\n Cancel\n </button>\n <button\n onClick={onSave}\n disabled={!apiKey || saving}\n className=\"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50\"\n >\n {testing ? \"Validating...\" : saving ? \"Saving...\" : isUrlBased ? \"Connect\" : \"Save\"}\n </button>\n </div>\n </div>\n ) : provider.hasKey ? (\n <div className=\"flex items-center justify-between\">\n {provider.docsUrl ? (\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#3b82f6] hover:underline\"\n >\n {isOllama ? \"Download Ollama\" : \"View docs\"}\n </a>\n ) : (\n <span />\n )}\n <div className=\"flex items-center gap-3\">\n <button\n onClick={onStartEdit}\n className=\"text-sm text-[#888] hover:text-[#e0e0e0]\"\n >\n {isUrlBased ? \"Change URL\" : \"Update key\"}\n </button>\n <button\n onClick={onDelete}\n className=\"text-red-400 hover:text-red-300 text-sm\"\n >\n Remove\n </button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-between\">\n {provider.docsUrl ? (\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#3b82f6] hover:underline\"\n >\n {isOllama ? \"Download Ollama\" : isBrowser ? \"View docs\" : \"Get API key\"}\n </a>\n ) : (\n <span />\n )}\n <button\n onClick={onStartEdit}\n className=\"text-sm text-[#f97316] hover:text-[#fb923c]\"\n >\n {isUrlBased ? \"Configure\" : \"+ Add key\"}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n}\n\ninterface IntegrationKey {\n id: string;\n provider_id: string;\n key_hint: string;\n is_valid: boolean;\n project_id: string | null;\n name: string | null;\n created_at: string;\n}\n\ninterface IntegrationKeyCardProps extends ProviderKeyCardProps {\n projectsEnabled: boolean;\n projects: Array<{ id: string; name: string; color: string }>;\n onRefresh: () => void;\n}\n\nfunction IntegrationKeyCard({\n provider,\n isEditing,\n apiKey,\n saving,\n testing,\n error,\n success,\n onStartEdit,\n onCancelEdit,\n onApiKeyChange,\n onSave,\n onDelete,\n projectsEnabled,\n projects,\n onRefresh,\n}: IntegrationKeyCardProps) {\n const { authFetch } = useAuth();\n const [keys, setKeys] = useState<IntegrationKey[]>([]);\n const [selectedProjectId, setSelectedProjectId] = useState<string>(\"\");\n const [expanded, setExpanded] = useState(false);\n const [localError, setLocalError] = useState<string | null>(null);\n const [localSaving, setLocalSaving] = useState(false);\n const { confirm, ConfirmDialog } = useConfirm();\n\n // Fetch all keys for this provider\n const fetchKeys = async () => {\n try {\n const res = await authFetch(`/api/keys/${provider.id}`);\n const data = await res.json();\n setKeys(data.keys || []);\n } catch (e) {\n console.error(\"Failed to fetch keys:\", e);\n }\n };\n\n useEffect(() => {\n if (projectsEnabled) {\n fetchKeys();\n }\n }, [provider.id, projectsEnabled]);\n\n // Clear local error when starting to edit\n useEffect(() => {\n if (isEditing) {\n setLocalError(null);\n }\n }, [isEditing]);\n\n const handleSaveWithProject = async () => {\n if (!apiKey) return;\n\n setLocalSaving(true);\n setLocalError(null);\n\n try {\n const res = await authFetch(`/api/keys/${provider.id}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n key: apiKey,\n project_id: selectedProjectId || null,\n }),\n });\n\n const data = await res.json();\n\n if (res.ok) {\n onApiKeyChange(\"\");\n setSelectedProjectId(\"\");\n onCancelEdit();\n fetchKeys();\n onRefresh();\n } else {\n setLocalError(data.error || \"Failed to save key\");\n }\n } catch (e) {\n console.error(\"Failed to save key:\", e);\n setLocalError(\"Failed to save key\");\n }\n setLocalSaving(false);\n };\n\n const handleDeleteKey = async (keyId: string, keyName: string | null) => {\n const confirmed = await confirm(\n `Are you sure you want to remove this API key${keyName ? ` (${keyName})` : \"\"}?`,\n { confirmText: \"Remove\", title: \"Remove API Key\" }\n );\n if (!confirmed) return;\n\n try {\n await authFetch(`/api/keys/by-id/${keyId}`, { method: \"DELETE\" });\n fetchKeys();\n onRefresh();\n } catch (e) {\n console.error(\"Failed to delete key:\", e);\n }\n };\n\n const globalKey = keys.find(k => !k.project_id);\n const projectKeys = keys.filter(k => k.project_id);\n const getProjectName = (projectId: string) => projects.find(p => p.id === projectId)?.name || \"Unknown\";\n const getProjectColor = (projectId: string) => projects.find(p => p.id === projectId)?.color || \"#666\";\n\n // Simple view when projects not enabled\n if (!projectsEnabled) {\n return (\n <div className={`bg-[#111] border rounded-lg p-4 ${\n provider.hasKey ? 'border-[#f97316]/20' : 'border-[#1a1a1a]'\n }`}>\n <div className=\"flex items-center justify-between mb-2\">\n <div>\n <h3 className=\"font-medium\">{provider.name}</h3>\n <p className=\"text-sm text-[#666]\">{provider.description || \"MCP integration\"}</p>\n </div>\n {provider.hasKey ? (\n <span className=\"text-[#f97316] text-xs flex items-center gap-1 bg-[#f97316]/10 px-2 py-1 rounded\">\n <CheckIcon className=\"w-3 h-3\" />\n {provider.keyHint}\n </span>\n ) : (\n <span className=\"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded\">\n Not configured\n </span>\n )}\n </div>\n\n <div className=\"mt-3 pt-3 border-t border-[#1a1a1a]\">\n {isEditing ? (\n <div className=\"space-y-3\">\n <input\n type=\"password\"\n value={apiKey}\n onChange={e => onApiKeyChange(e.target.value)}\n placeholder={provider.hasKey ? \"Enter new API key...\" : \"Enter API key...\"}\n autoFocus\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n {success && <p className=\"text-green-400 text-sm\">{success}</p>}\n <div className=\"flex gap-2\">\n <button\n onClick={onCancelEdit}\n className=\"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]\"\n >\n Cancel\n </button>\n <button\n onClick={onSave}\n disabled={!apiKey || saving}\n className=\"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50\"\n >\n {testing ? \"Validating...\" : saving ? \"Saving...\" : \"Save\"}\n </button>\n </div>\n </div>\n ) : provider.hasKey ? (\n <div className=\"flex items-center justify-between\">\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#3b82f6] hover:underline\"\n >\n View docs\n </a>\n <div className=\"flex items-center gap-3\">\n <button\n onClick={onStartEdit}\n className=\"text-sm text-[#888] hover:text-[#e0e0e0]\"\n >\n Update key\n </button>\n <button\n onClick={onDelete}\n className=\"text-red-400 hover:text-red-300 text-sm\"\n >\n Remove\n </button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-between\">\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#3b82f6] hover:underline\"\n >\n Get API key\n </a>\n <button\n onClick={onStartEdit}\n className=\"text-sm text-[#f97316] hover:text-[#fb923c]\"\n >\n + Add key\n </button>\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Enhanced view with project support\n return (\n <>\n {ConfirmDialog}\n <div className={`bg-[#111] border rounded-lg p-4 ${\n keys.length > 0 ? 'border-[#f97316]/20' : 'border-[#1a1a1a]'\n }`}>\n <div className=\"flex items-center justify-between mb-2\">\n <div>\n <h3 className=\"font-medium\">{provider.name}</h3>\n <p className=\"text-sm text-[#666]\">{provider.description || \"MCP integration\"}</p>\n </div>\n {keys.length > 0 ? (\n <span className=\"text-[#f97316] text-xs flex items-center gap-1 bg-[#f97316]/10 px-2 py-1 rounded\">\n <CheckIcon className=\"w-3 h-3\" />\n {keys.length} key{keys.length !== 1 ? \"s\" : \"\"}\n </span>\n ) : (\n <span className=\"text-[#666] text-xs bg-[#1a1a1a] px-2 py-1 rounded\">\n Not configured\n </span>\n )}\n </div>\n\n {/* Keys List */}\n {keys.length > 0 && (\n <div className=\"mt-3 space-y-2\">\n {/* Global Key */}\n {globalKey && (\n <div className=\"flex items-center justify-between text-sm bg-[#0a0a0a] rounded px-3 py-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-[#888]\">Global</span>\n <span className=\"text-[#555]\">·</span>\n <span className=\"text-[#666] font-mono text-xs\">{globalKey.key_hint}</span>\n </div>\n <button\n onClick={() => handleDeleteKey(globalKey.id, \"Global\")}\n className=\"text-red-400 hover:text-red-300 text-xs\"\n >\n Remove\n </button>\n </div>\n )}\n\n {/* Project Keys - show first 2, expand for more */}\n {projectKeys.slice(0, expanded ? undefined : 2).map(key => (\n <div key={key.id} className=\"flex items-center justify-between text-sm bg-[#0a0a0a] rounded px-3 py-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className=\"w-2 h-2 rounded-full flex-shrink-0\"\n style={{ backgroundColor: getProjectColor(key.project_id!) }}\n />\n <span className=\"text-[#888] truncate\">{key.name || getProjectName(key.project_id!)}</span>\n <span className=\"text-[#555]\">·</span>\n <span className=\"text-[#666] font-mono text-xs\">{key.key_hint}</span>\n </div>\n <button\n onClick={() => handleDeleteKey(key.id, key.name || getProjectName(key.project_id!))}\n className=\"text-red-400 hover:text-red-300 text-xs flex-shrink-0 ml-2\"\n >\n Remove\n </button>\n </div>\n ))}\n\n {projectKeys.length > 2 && !expanded && (\n <button\n onClick={() => setExpanded(true)}\n className=\"text-xs text-[#666] hover:text-[#888] w-full text-center py-1\"\n >\n Show {projectKeys.length - 2} more...\n </button>\n )}\n </div>\n )}\n\n <div className=\"mt-3 pt-3 border-t border-[#1a1a1a]\">\n {isEditing ? (\n <div className=\"space-y-3\">\n <input\n type=\"password\"\n value={apiKey}\n onChange={e => onApiKeyChange(e.target.value)}\n placeholder=\"Enter API key...\"\n autoFocus\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n\n <Select\n value={selectedProjectId}\n onChange={setSelectedProjectId}\n placeholder=\"Global (all projects)\"\n options={[\n { value: \"\", label: \"Global (all projects)\" },\n ...projects.map(p => ({ value: p.id, label: p.name }))\n ]}\n />\n\n {localError && <p className=\"text-red-400 text-sm\">{localError}</p>}\n\n <div className=\"flex gap-2\">\n <button\n onClick={() => {\n onCancelEdit();\n setSelectedProjectId(\"\");\n setLocalError(null);\n }}\n className=\"flex-1 px-3 py-1.5 border border-[#333] rounded text-sm hover:border-[#666]\"\n >\n Cancel\n </button>\n <button\n onClick={handleSaveWithProject}\n disabled={!apiKey || localSaving}\n className=\"flex-1 px-3 py-1.5 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50\"\n >\n {localSaving ? \"Saving...\" : \"Save\"}\n </button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-between\">\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#3b82f6] hover:underline\"\n >\n {keys.length > 0 ? \"View docs\" : \"Get API key\"}\n </a>\n <button\n onClick={onStartEdit}\n className=\"text-sm text-[#f97316] hover:text-[#fb923c]\"\n >\n + Add key\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n}\n\ninterface ApiKeyItem {\n id: string;\n name: string;\n prefix: string;\n is_active: boolean;\n expires_at: string | null;\n last_used_at: string | null;\n created_at: string;\n}\n\nfunction ApiKeysSettings() {\n const { authFetch } = useAuth();\n const [keys, setKeys] = useState<ApiKeyItem[]>([]);\n const [showCreate, setShowCreate] = useState(false);\n const [name, setName] = useState(\"\");\n const [expiresInDays, setExpiresInDays] = useState<string>(\"90\");\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [newKey, setNewKey] = useState<string | null>(null);\n const [copied, setCopied] = useState(false);\n const { confirm, ConfirmDialog } = useConfirm();\n\n const fetchKeys = async () => {\n try {\n const res = await authFetch(\"/api/keys/personal\");\n const data = await res.json();\n setKeys(data.keys || []);\n } catch {\n // ignore\n }\n };\n\n useEffect(() => {\n fetchKeys();\n }, []);\n\n const handleCreate = async () => {\n if (!name.trim()) {\n setError(\"Name is required\");\n return;\n }\n setCreating(true);\n setError(null);\n\n try {\n const res = await authFetch(\"/api/keys/personal\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n name: name.trim(),\n expires_in_days: expiresInDays ? parseInt(expiresInDays) : null,\n }),\n });\n\n const data = await res.json();\n if (!res.ok) {\n setError(data.error || \"Failed to create key\");\n } else {\n setNewKey(data.key);\n setName(\"\");\n setExpiresInDays(\"90\");\n fetchKeys();\n }\n } catch {\n setError(\"Failed to create key\");\n }\n setCreating(false);\n };\n\n const handleDelete = async (id: string, keyName: string) => {\n const confirmed = await confirm(`Delete API key \"${keyName}\"? This cannot be undone.`, { confirmText: \"Delete\", title: \"Delete API Key\" });\n if (!confirmed) return;\n\n try {\n await authFetch(`/api/keys/personal/${id}`, { method: \"DELETE\" });\n fetchKeys();\n } catch {\n // ignore\n }\n };\n\n const copyKey = () => {\n if (newKey) {\n navigator.clipboard.writeText(newKey);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n const formatDate = (dateStr: string | null) => {\n if (!dateStr) return \"Never\";\n const d = new Date(dateStr);\n return d.toLocaleDateString(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" });\n };\n\n const isExpired = (expiresAt: string | null) => {\n if (!expiresAt) return false;\n return new Date(expiresAt) < new Date();\n };\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6 flex items-center justify-between gap-4\">\n <div>\n <h1 className=\"text-2xl font-semibold mb-1\">API Keys</h1>\n <p className=\"text-[#666]\">\n Create personal API keys for programmatic access. Use them with the <code className=\"text-[#888] bg-[#1a1a1a] px-1 rounded text-xs\">X-API-Key</code> header.\n </p>\n </div>\n {!showCreate && !newKey && (\n <button\n onClick={() => { setShowCreate(true); setError(null); }}\n className=\"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition flex-shrink-0\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n New Key\n </button>\n )}\n </div>\n\n {/* Newly created key - show once */}\n {newKey && (\n <div className=\"bg-green-500/10 border border-green-500/30 rounded-lg p-4 mb-6\">\n <div className=\"flex items-center gap-2 text-green-400 mb-2\">\n <CheckIcon className=\"w-5 h-5\" />\n <span className=\"font-medium\">API key created</span>\n </div>\n <p className=\"text-sm text-[#888] mb-3\">\n Copy this key now. You won't be able to see it again.\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"flex-1 bg-[#0a0a0a] px-3 py-2 rounded font-mono text-sm text-[#e0e0e0] break-all select-all\">\n {newKey}\n </code>\n <button\n onClick={copyKey}\n className=\"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] rounded text-sm flex-shrink-0\"\n >\n {copied ? \"Copied!\" : \"Copy\"}\n </button>\n </div>\n <button\n onClick={() => { setNewKey(null); setShowCreate(false); }}\n className=\"mt-3 text-sm text-[#666] hover:text-[#888]\"\n >\n Done\n </button>\n </div>\n )}\n\n {/* Create Form */}\n {showCreate && !newKey && (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 mb-6\">\n <h3 className=\"font-medium mb-4\">Create new API key</h3>\n <div className=\"space-y-4 max-w-md\">\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Name</label>\n <input\n type=\"text\"\n value={name}\n onChange={e => setName(e.target.value)}\n placeholder=\"e.g. CI Pipeline, My Script\"\n autoFocus\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Expiration</label>\n <select\n value={expiresInDays}\n onChange={e => setExpiresInDays(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n >\n <option value=\"30\">30 days</option>\n <option value=\"90\">90 days</option>\n <option value=\"180\">180 days</option>\n <option value=\"365\">1 year</option>\n <option value=\"\">No expiration</option>\n </select>\n </div>\n\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n\n <div className=\"flex gap-2\">\n <button\n onClick={() => { setShowCreate(false); setError(null); setName(\"\"); }}\n className=\"flex-1 px-3 py-2 border border-[#333] rounded text-sm hover:border-[#666]\"\n >\n Cancel\n </button>\n <button\n onClick={handleCreate}\n disabled={creating || !name.trim()}\n className=\"flex-1 px-3 py-2 bg-[#f97316] text-black rounded text-sm font-medium disabled:opacity-50\"\n >\n {creating ? \"Creating...\" : \"Create Key\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Keys List */}\n {keys.length === 0 ? (\n <div className=\"text-center py-12 text-[#666]\">\n <p className=\"text-lg mb-2\">No API keys yet</p>\n <p className=\"text-sm\">Create an API key to access apteva programmatically.</p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {keys.map(key => (\n <div\n key={key.id}\n className={`bg-[#111] border rounded-lg p-4 flex items-center gap-4 ${\n !key.is_active || isExpired(key.expires_at) ? \"border-[#1a1a1a] opacity-60\" : \"border-[#1a1a1a]\"\n }`}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <h3 className=\"font-medium\">{key.name}</h3>\n {!key.is_active && (\n <span className=\"text-xs text-red-400 bg-red-500/10 px-2 py-0.5 rounded\">Revoked</span>\n )}\n {key.is_active && isExpired(key.expires_at) && (\n <span className=\"text-xs text-yellow-400 bg-yellow-500/10 px-2 py-0.5 rounded\">Expired</span>\n )}\n </div>\n <div className=\"flex items-center gap-3 text-sm text-[#666]\">\n <code className=\"font-mono text-xs bg-[#0a0a0a] px-2 py-0.5 rounded\">{key.prefix}...</code>\n <span>Created {formatDate(key.created_at)}</span>\n {key.expires_at && <span>Expires {formatDate(key.expires_at)}</span>}\n {key.last_used_at && <span>Last used {formatDate(key.last_used_at)}</span>}\n </div>\n </div>\n {key.is_active && (\n <button\n onClick={() => handleDelete(key.id, key.name)}\n className=\"text-sm text-red-400 hover:text-red-300 px-2 py-1 flex-shrink-0\"\n >\n Delete\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* Usage Info */}\n {keys.length > 0 && (\n <div className=\"mt-6 bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <h3 className=\"font-medium mb-2 text-sm\">Usage</h3>\n <code className=\"block bg-[#0a0a0a] px-3 py-2 rounded font-mono text-xs text-[#888]\">\n curl -H \"X-API-Key: apt_...\" http://localhost:4280/api/agents\n </code>\n </div>\n )}\n </div>\n </>\n );\n}\n\nfunction AccountSettings() {\n const { authFetch, user } = useAuth();\n const [currentPassword, setCurrentPassword] = useState(\"\");\n const [newPassword, setNewPassword] = useState(\"\");\n const [confirmPassword, setConfirmPassword] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [message, setMessage] = useState<{ type: \"success\" | \"error\"; text: string } | null>(null);\n\n const handleChangePassword = async () => {\n // Validation\n if (!currentPassword || !newPassword || !confirmPassword) {\n setMessage({ type: \"error\", text: \"All fields are required\" });\n return;\n }\n\n if (newPassword !== confirmPassword) {\n setMessage({ type: \"error\", text: \"New passwords do not match\" });\n return;\n }\n\n if (newPassword.length < 8) {\n setMessage({ type: \"error\", text: \"Password must be at least 8 characters\" });\n return;\n }\n\n setSaving(true);\n setMessage(null);\n\n try {\n const res = await authFetch(\"/api/auth/password\", {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ currentPassword, newPassword }),\n });\n\n const data = await res.json();\n\n if (res.ok) {\n setMessage({ type: \"success\", text: \"Password updated successfully\" });\n setCurrentPassword(\"\");\n setNewPassword(\"\");\n setConfirmPassword(\"\");\n } else {\n setMessage({ type: \"error\", text: data.error || \"Failed to update password\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to update password\" });\n }\n\n setSaving(false);\n };\n\n return (\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold mb-1\">Account Settings</h1>\n <p className=\"text-[#666]\">Manage your account and security.</p>\n </div>\n\n {/* User Info */}\n {user && (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 mb-6\">\n <h3 className=\"font-medium mb-3\">Profile</h3>\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-[#666]\">Username</span>\n <span>{user.username}</span>\n </div>\n {user.email && (\n <div className=\"flex justify-between\">\n <span className=\"text-[#666]\">Email</span>\n <span>{user.email}</span>\n </div>\n )}\n <div className=\"flex justify-between\">\n <span className=\"text-[#666]\">Role</span>\n <span className=\"capitalize\">{user.role}</span>\n </div>\n </div>\n </div>\n )}\n\n {/* Change Password */}\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <h3 className=\"font-medium mb-4\">Change Password</h3>\n\n <div className=\"space-y-4 max-w-md\">\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Current Password</label>\n <input\n type=\"password\"\n value={currentPassword}\n onChange={(e) => setCurrentPassword(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">New Password</label>\n <input\n type=\"password\"\n value={newPassword}\n onChange={(e) => setNewPassword(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Confirm New Password</label>\n <input\n type=\"password\"\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n {message && (\n <div className={`p-3 rounded text-sm ${\n message.type === \"success\"\n ? \"bg-green-500/10 text-green-400 border border-green-500/30\"\n : \"bg-red-500/10 text-red-400 border border-red-500/30\"\n }`}>\n {message.text}\n </div>\n )}\n\n <button\n onClick={handleChangePassword}\n disabled={saving || !currentPassword || !newPassword || !confirmPassword}\n className=\"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 disabled:cursor-not-allowed text-black rounded text-sm font-medium transition\"\n >\n {saving ? \"Updating...\" : \"Update Password\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction DataSettings() {\n const { authFetch } = useAuth();\n const [clearing, setClearing] = useState(false);\n const [message, setMessage] = useState<{ type: \"success\" | \"error\"; text: string } | null>(null);\n const [eventCount, setEventCount] = useState<number | null>(null);\n const { confirm, ConfirmDialog } = useConfirm();\n\n const fetchStats = async () => {\n try {\n const res = await authFetch(\"/api/telemetry/stats\");\n const data = await res.json();\n setEventCount(data.stats?.total_events || 0);\n } catch {\n setEventCount(null);\n }\n };\n\n useEffect(() => {\n fetchStats();\n }, []);\n\n const clearTelemetry = async () => {\n const confirmed = await confirm(\"Are you sure you want to delete all telemetry data? This cannot be undone.\", { confirmText: \"Clear All\", title: \"Clear Telemetry Data\" });\n if (!confirmed) return;\n\n setClearing(true);\n setMessage(null);\n\n try {\n const res = await authFetch(\"/api/telemetry/clear\", { method: \"POST\" });\n const data = await res.json();\n\n if (res.ok) {\n setMessage({ type: \"success\", text: `Cleared ${data.deleted || 0} telemetry events.` });\n setEventCount(0);\n } else {\n setMessage({ type: \"error\", text: data.error || \"Failed to clear telemetry\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to clear telemetry\" });\n }\n\n setClearing(false);\n };\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"max-w-4xl w-full\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold mb-1\">Data Management</h1>\n <p className=\"text-[#666]\">Manage stored data and telemetry.</p>\n </div>\n\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <h3 className=\"font-medium mb-2\">Telemetry Data</h3>\n <p className=\"text-sm text-[#666] mb-4\">\n {eventCount !== null\n ? `${eventCount.toLocaleString()} events stored`\n : \"Loading...\"}\n </p>\n\n {message && (\n <div className={`mb-4 p-3 rounded text-sm ${\n message.type === \"success\"\n ? \"bg-green-500/10 text-green-400 border border-green-500/30\"\n : \"bg-red-500/10 text-red-400 border border-red-500/30\"\n }`}>\n {message.text}\n </div>\n )}\n\n <button\n onClick={clearTelemetry}\n disabled={clearing || eventCount === 0}\n className=\"px-4 py-2 bg-red-500/20 text-red-400 hover:bg-red-500/30 disabled:opacity-50 disabled:cursor-not-allowed rounded text-sm font-medium transition\"\n >\n {clearing ? \"Clearing...\" : \"Clear All Telemetry\"}\n </button>\n </div>\n </div>\n </>\n );\n}\n\n// --- Channels Settings ---\n\ninterface ChannelInfo {\n id: string;\n type: string;\n name: string;\n agent_id: string;\n status: \"stopped\" | \"running\" | \"error\";\n error: string | null;\n created_at: string;\n}\n\ninterface AgentOption {\n id: string;\n name: string;\n status: string;\n}\n\nfunction ChannelsSettings() {\n const { authFetch } = useAuth();\n const [channels, setChannels] = useState<ChannelInfo[]>([]);\n const [agents, setAgents] = useState<AgentOption[]>([]);\n const [loading, setLoading] = useState(true);\n const [showForm, setShowForm] = useState(false);\n const [formData, setFormData] = useState({ name: \"\", agent_id: \"\", botToken: \"\" });\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const { confirm, ConfirmDialog } = useConfirm();\n\n const fetchChannels = async () => {\n try {\n const res = await authFetch(\"/api/channels\");\n const data = await res.json();\n setChannels(data.channels || []);\n } catch {\n // Ignore\n } finally {\n setLoading(false);\n }\n };\n\n const fetchAgents = async () => {\n try {\n const res = await authFetch(\"/api/agents\");\n const data = await res.json();\n setAgents((data.agents || []).map((a: any) => ({ id: a.id, name: a.name, status: a.status })));\n } catch {\n // Ignore\n }\n };\n\n useEffect(() => {\n fetchChannels();\n fetchAgents();\n }, []);\n\n const createChannel = async () => {\n if (!formData.name || !formData.agent_id || !formData.botToken) return;\n setCreating(true);\n setError(null);\n\n try {\n const res = await authFetch(\"/api/channels\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n type: \"telegram\",\n name: formData.name,\n agent_id: formData.agent_id,\n config: { botToken: formData.botToken },\n }),\n });\n\n if (!res.ok) {\n const data = await res.json();\n setError(data.error || \"Failed to create channel\");\n } else {\n setFormData({ name: \"\", agent_id: \"\", botToken: \"\" });\n setShowForm(false);\n await fetchChannels();\n }\n } catch (err: any) {\n setError(err.message);\n } finally {\n setCreating(false);\n }\n };\n\n const toggleChannel = async (channel: ChannelInfo) => {\n const action = channel.status === \"running\" ? \"stop\" : \"start\";\n try {\n const res = await authFetch(`/api/channels/${channel.id}/${action}`, { method: \"POST\" });\n if (!res.ok) {\n const data = await res.json();\n setError(data.error || `Failed to ${action} channel`);\n }\n await fetchChannels();\n } catch {\n setError(`Failed to ${action} channel`);\n }\n };\n\n const deleteChannel = async (channel: ChannelInfo) => {\n const confirmed = await confirm(`Delete channel \"${channel.name}\"?`, {\n confirmText: \"Delete\",\n title: \"Delete Channel\",\n });\n if (!confirmed) return;\n\n try {\n await authFetch(`/api/channels/${channel.id}`, { method: \"DELETE\" });\n await fetchChannels();\n } catch {\n // Ignore\n }\n };\n\n const statusColors: Record<string, string> = {\n running: \"bg-green-500/20 text-green-400\",\n stopped: \"bg-[#333] text-[#666]\",\n error: \"bg-red-500/20 text-red-400\",\n };\n\n const getAgentName = (agentId: string) => {\n return agents.find(a => a.id === agentId)?.name || agentId;\n };\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"max-w-2xl\">\n <div className=\"flex items-center justify-between mb-6\">\n <div>\n <h2 className=\"text-xl font-semibold mb-1\">Channels</h2>\n <p className=\"text-sm text-[#666]\">Connect agents to external messaging platforms</p>\n </div>\n <button\n onClick={() => setShowForm(!showForm)}\n className=\"flex items-center gap-2 bg-[#f97316] hover:bg-[#fb923c] text-black px-3 py-1.5 rounded text-sm font-medium transition\"\n >\n <PlusIcon /> Add Channel\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-500/10 text-red-400 border border-red-500/30 px-3 py-2 rounded text-sm flex items-center justify-between\">\n <span>{error}</span>\n <button onClick={() => setError(null)} className=\"text-red-400 hover:text-red-300 ml-2\">\n <CloseIcon />\n </button>\n </div>\n )}\n\n {/* Create form */}\n {showForm && (\n <div className=\"mb-6 bg-[#111] border border-[#1a1a1a] rounded-lg p-4 space-y-3\">\n <h3 className=\"text-sm font-medium text-[#888] mb-2\">New Telegram Channel</h3>\n\n <div>\n <label className=\"block text-xs text-[#666] mb-1\">Channel Name</label>\n <input\n type=\"text\"\n value={formData.name}\n onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}\n placeholder=\"e.g. My Telegram Bot\"\n className=\"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs text-[#666] mb-1\">Agent</label>\n <Select\n value={formData.agent_id}\n options={agents.map(a => ({ value: a.id, label: a.name }))}\n onChange={value => setFormData(prev => ({ ...prev, agent_id: value }))}\n placeholder=\"Select an agent...\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs text-[#666] mb-1\">Bot Token</label>\n <input\n type=\"password\"\n value={formData.botToken}\n onChange={e => setFormData(prev => ({ ...prev, botToken: e.target.value }))}\n placeholder=\"From @BotFather on Telegram\"\n className=\"w-full bg-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Create a bot via <a href=\"https://t.me/BotFather\" target=\"_blank\" className=\"text-[#f97316] hover:underline\">@BotFather</a> on Telegram to get a token.\n </p>\n </div>\n\n <div className=\"flex gap-2 pt-1\">\n <button\n onClick={createChannel}\n disabled={creating || !formData.name || !formData.agent_id || !formData.botToken}\n className=\"bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-4 py-1.5 rounded text-sm font-medium transition\"\n >\n {creating ? \"Creating...\" : \"Create\"}\n </button>\n <button\n onClick={() => { setShowForm(false); setFormData({ name: \"\", agent_id: \"\", botToken: \"\" }); }}\n className=\"border border-[#333] hover:border-[#444] px-4 py-1.5 rounded text-sm transition\"\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {/* Channel list */}\n {loading ? (\n <p className=\"text-[#666] text-sm\">Loading channels...</p>\n ) : channels.length === 0 ? (\n <div className=\"text-center py-12 text-[#666]\">\n <p className=\"text-lg mb-2\">No channels configured</p>\n <p className=\"text-sm\">Add a Telegram channel to let users message your agents directly.</p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {channels.map(channel => (\n <div key={channel.id} className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <h3 className=\"font-medium\">{channel.name}</h3>\n <span className={`px-2 py-0.5 rounded text-xs font-medium ${statusColors[channel.status] || statusColors.stopped}`}>\n {channel.status}\n </span>\n </div>\n <p className=\"text-sm text-[#666]\">\n {channel.type === \"telegram\" ? \"Telegram\" : channel.type} → {getAgentName(channel.agent_id)}\n </p>\n {channel.status === \"error\" && channel.error && (\n <p className=\"text-xs text-red-400 mt-1\">{channel.error}</p>\n )}\n </div>\n <div className=\"flex items-center gap-2 ml-4\">\n <button\n onClick={() => toggleChannel(channel)}\n className={`px-3 py-1 rounded text-xs font-medium transition ${\n channel.status === \"running\"\n ? \"bg-[#f97316]/20 text-[#f97316] hover:bg-[#f97316]/30\"\n : \"bg-[#3b82f6]/20 text-[#3b82f6] hover:bg-[#3b82f6]/30\"\n }`}\n >\n {channel.status === \"running\" ? \"Stop\" : \"Start\"}\n </button>\n <button\n onClick={() => deleteChannel(channel)}\n className=\"text-[#666] hover:text-red-400 transition text-sm\"\n >\n ×\n </button>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </>\n );\n}\n\nfunction AssistantSettings() {\n const { authFetch } = useAuth();\n const [providers, setProviders] = useState<Provider[]>([]);\n const [provider, setProvider] = useState(\"\");\n const [model, setModel] = useState(\"\");\n const [systemPrompt, setSystemPrompt] = useState(\"\");\n const [status, setStatus] = useState<\"running\" | \"stopped\" | \"unknown\">(\"unknown\");\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [message, setMessage] = useState<{ type: \"success\" | \"error\"; text: string } | null>(null);\n const [starting, setStarting] = useState(false);\n\n // Original values for change detection\n const [original, setOriginal] = useState({ provider: \"\", model: \"\", systemPrompt: \"\" });\n\n useEffect(() => {\n const fetchData = async () => {\n try {\n const [statusRes, providersRes] = await Promise.all([\n authFetch(\"/api/meta-agent/status\"),\n authFetch(\"/api/providers\"),\n ]);\n const statusData = await statusRes.json();\n const providersData = await providersRes.json();\n setProviders((providersData.providers || []).filter((p: Provider) => p.type === \"llm\" && p.hasKey));\n\n if (statusData.agent) {\n const a = statusData.agent;\n setProvider(a.provider || \"\");\n setModel(a.model || \"\");\n setSystemPrompt(a.systemPrompt || \"\");\n setStatus(a.status || \"stopped\");\n setOriginal({ provider: a.provider || \"\", model: a.model || \"\", systemPrompt: a.systemPrompt || \"\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to load assistant config\" });\n } finally {\n setLoading(false);\n }\n };\n fetchData();\n }, [authFetch]);\n\n const selectedProvider = providers.find(p => p.id === provider);\n const models = selectedProvider?.models || [];\n\n const handleProviderChange = (newProvider: string) => {\n setProvider(newProvider);\n const p = providers.find(pr => pr.id === newProvider);\n const defaultModel = p?.models.find(m => m.recommended)?.value || p?.models[0]?.value || \"\";\n setModel(defaultModel);\n };\n\n const hasChanges = provider !== original.provider || model !== original.model || systemPrompt !== original.systemPrompt;\n\n const handleSave = async () => {\n setSaving(true);\n setMessage(null);\n try {\n const res = await authFetch(\"/api/agents/apteva-assistant\", {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ provider, model, systemPrompt }),\n });\n if (res.ok) {\n setOriginal({ provider, model, systemPrompt });\n setMessage({ type: \"success\", text: \"Assistant settings saved\" });\n setTimeout(() => setMessage(null), 3000);\n } else {\n const data = await res.json().catch(() => ({}));\n setMessage({ type: \"error\", text: data.error || \"Failed to save\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to save settings\" });\n } finally {\n setSaving(false);\n }\n };\n\n const handleToggle = async () => {\n setStarting(true);\n setMessage(null);\n try {\n const endpoint = status === \"running\" ? \"/api/meta-agent/stop\" : \"/api/meta-agent/start\";\n const res = await authFetch(endpoint, { method: \"POST\" });\n if (res.ok) {\n setStatus(status === \"running\" ? \"stopped\" : \"running\");\n } else {\n const data = await res.json().catch(() => ({}));\n setMessage({ type: \"error\", text: data.error || \"Failed to toggle assistant\" });\n }\n } catch {\n setMessage({ type: \"error\", text: \"Failed to toggle assistant\" });\n } finally {\n setStarting(false);\n }\n };\n\n if (loading) {\n return <div className=\"text-[#666]\">Loading assistant settings...</div>;\n }\n\n return (\n <div className=\"max-w-2xl\">\n <h2 className=\"text-lg font-medium mb-1\">Apteva Assistant</h2>\n <p className=\"text-sm text-[#666] mb-6\">Configure the built-in AI assistant that manages your agents and platform.</p>\n\n {message && (\n <div className={`mb-4 px-3 py-2 rounded text-sm ${\n message.type === \"success\" ? \"bg-green-500/10 text-green-400\" : \"bg-red-500/10 text-red-400\"\n }`}>\n {message.text}\n </div>\n )}\n\n {/* Status */}\n <div className=\"mb-6 flex items-center gap-3\">\n <span className=\"text-sm text-[#666]\">Status:</span>\n <span className={`px-2 py-1 rounded text-xs font-medium ${\n status === \"running\" ? \"bg-[#3b82f6]/20 text-[#3b82f6]\" : \"bg-[#333] text-[#666]\"\n }`}>\n {status}\n </span>\n <button\n onClick={handleToggle}\n disabled={starting}\n className={`px-3 py-1.5 rounded text-sm font-medium transition ${\n status === \"running\"\n ? \"bg-[#f97316]/20 text-[#f97316] hover:bg-[#f97316]/30\"\n : \"bg-[#3b82f6]/20 text-[#3b82f6] hover:bg-[#3b82f6]/30\"\n } disabled:opacity-50`}\n >\n {starting ? \"...\" : status === \"running\" ? \"Stop\" : \"Start\"}\n </button>\n </div>\n\n {/* Provider */}\n <div className=\"mb-4\">\n <label className=\"block text-sm text-[#666] mb-1\">Provider</label>\n <Select\n value={provider}\n onChange={handleProviderChange}\n options={providers.map(p => ({ value: p.id, label: p.name }))}\n placeholder=\"Select provider...\"\n />\n </div>\n\n {/* Model */}\n <div className=\"mb-4\">\n <label className=\"block text-sm text-[#666] mb-1\">Model</label>\n <Select\n value={model}\n onChange={setModel}\n options={models.map(m => ({ value: m.value, label: m.label, recommended: m.recommended }))}\n placeholder=\"Select model...\"\n />\n </div>\n\n {/* System Prompt */}\n <div className=\"mb-6\">\n <label className=\"block text-sm text-[#666] mb-1\">System Prompt</label>\n <textarea\n value={systemPrompt}\n onChange={e => setSystemPrompt(e.target.value)}\n rows={12}\n className=\"w-full bg-[#111] border border-[#1a1a1a] rounded px-3 py-2 text-sm font-mono focus:outline-none focus:border-[#f97316] resize-y\"\n />\n </div>\n\n {/* Save */}\n <button\n onClick={handleSave}\n disabled={!hasChanges || saving}\n className=\"bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 disabled:cursor-not-allowed text-black px-4 py-2 rounded font-medium transition\"\n >\n {saving ? \"Saving...\" : \"Save Changes\"}\n </button>\n\n {status === \"running\" && hasChanges && (\n <p className=\"text-xs text-[#666] mt-2\">Changes will be applied to the running assistant</p>\n )}\n </div>\n );\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "A7AC98F21789CBAB64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|