@apteva/apteva-darwin-arm64 0.4.41 → 0.4.48

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.
Files changed (94) hide show
  1. package/apteva +0 -0
  2. package/dist/ActivityPage.9v5ha2p7.js +3 -0
  3. package/dist/{ActivityPage.7907h64p.js.map → ActivityPage.9v5ha2p7.js.map} +3 -3
  4. package/dist/ApiDocsPage.qsehxvkb.js +4 -0
  5. package/dist/ApiDocsPage.qsehxvkb.js.map +10 -0
  6. package/dist/App.168av39e.js +221 -0
  7. package/dist/{App.qcknavjz.js.map → App.168av39e.js.map} +15 -15
  8. package/dist/App.2j20h2gt.js +8 -0
  9. package/dist/App.2j20h2gt.js.map +12 -0
  10. package/dist/App.7gj4jht5.js +53 -0
  11. package/dist/{App.apjrmctz.js.map → App.7gj4jht5.js.map} +50 -52
  12. package/dist/App.aexwv4rk.js +4 -0
  13. package/dist/App.aexwv4rk.js.map +10 -0
  14. package/dist/App.anvw0hjc.js +61 -0
  15. package/dist/App.anvw0hjc.js.map +13 -0
  16. package/dist/App.cjcyr5aj.js +4 -0
  17. package/dist/App.cjcyr5aj.js.map +10 -0
  18. package/dist/App.dmvykj97.js +4 -0
  19. package/dist/App.dmvykj97.js.map +10 -0
  20. package/dist/App.e2kkda2a.js +4 -0
  21. package/dist/App.e2kkda2a.js.map +10 -0
  22. package/dist/App.j4ec9k18.js +13 -0
  23. package/dist/App.j4ec9k18.js.map +10 -0
  24. package/dist/{App.7fb3e7mp.js → App.jdkx6eqd.js} +1 -1
  25. package/dist/App.kz3qyyre.js +4 -0
  26. package/dist/{App.myxqcj9x.js.map → App.kz3qyyre.js.map} +3 -3
  27. package/dist/App.sd685nt9.js +4 -0
  28. package/dist/App.sd685nt9.js.map +10 -0
  29. package/dist/App.shfd8tp9.js +20 -0
  30. package/dist/{App.3qw8nben.js.map → App.shfd8tp9.js.map} +6 -4
  31. package/dist/App.wghtdzsk.js +1 -0
  32. package/dist/App.x6x8s16g.js +4 -0
  33. package/dist/App.x6x8s16g.js.map +14 -0
  34. package/dist/App.y2vn8m06.js +4 -0
  35. package/dist/App.y2vn8m06.js.map +10 -0
  36. package/dist/ConnectionsPage.1dyyfqbk.js +3 -0
  37. package/dist/McpPage.xvr8hk05.js +3 -0
  38. package/dist/SettingsPage.5jmnefwe.js +3 -0
  39. package/dist/SkillsPage.jw7carjq.js +3 -0
  40. package/dist/TasksPage.r8txe0e9.js +3 -0
  41. package/dist/TasksPage.r8txe0e9.js.map +9 -0
  42. package/dist/TelemetryPage.pcafk41x.js +3 -0
  43. package/dist/TelemetryPage.pcafk41x.js.map +9 -0
  44. package/dist/TestsPage.pkymr7yt.js +3 -0
  45. package/dist/ThreadsPage.49tgq4fq.js +3 -0
  46. package/dist/apteva-kit.css +1 -1
  47. package/dist/index.html +1 -1
  48. package/dist/styles.css +1 -1
  49. package/package.json +1 -1
  50. package/dist/ActivityPage.7907h64p.js +0 -3
  51. package/dist/ApiDocsPage.k3jjenpq.js +0 -4
  52. package/dist/ApiDocsPage.k3jjenpq.js.map +0 -10
  53. package/dist/App.01nq20st.js +0 -4
  54. package/dist/App.01nq20st.js.map +0 -10
  55. package/dist/App.1maqvamf.js +0 -4
  56. package/dist/App.1maqvamf.js.map +0 -14
  57. package/dist/App.2yjrh32f.js +0 -4
  58. package/dist/App.2yjrh32f.js.map +0 -10
  59. package/dist/App.3qw8nben.js +0 -20
  60. package/dist/App.7sy3wq8c.js +0 -4
  61. package/dist/App.7sy3wq8c.js.map +0 -10
  62. package/dist/App.apjrmctz.js +0 -57
  63. package/dist/App.av6t2yhe.js +0 -4
  64. package/dist/App.av6t2yhe.js.map +0 -10
  65. package/dist/App.jqj5a094.js +0 -46
  66. package/dist/App.jqj5a094.js.map +0 -13
  67. package/dist/App.mc7xf85h.js +0 -4
  68. package/dist/App.mc7xf85h.js.map +0 -10
  69. package/dist/App.myxqcj9x.js +0 -4
  70. package/dist/App.nm91r1mp.js +0 -13
  71. package/dist/App.nm91r1mp.js.map +0 -10
  72. package/dist/App.p02f4ret.js +0 -1
  73. package/dist/App.qcknavjz.js +0 -221
  74. package/dist/App.vc7vfhg4.js +0 -4
  75. package/dist/App.vc7vfhg4.js.map +0 -10
  76. package/dist/App.z4s9zkw5.js +0 -4
  77. package/dist/App.z4s9zkw5.js.map +0 -10
  78. package/dist/ConnectionsPage.z1pw5xe2.js +0 -3
  79. package/dist/McpPage.8vc97z0b.js +0 -3
  80. package/dist/SettingsPage.p61bz8kd.js +0 -3
  81. package/dist/SkillsPage.r9x43g3g.js +0 -3
  82. package/dist/TasksPage.1e0zkye4.js +0 -3
  83. package/dist/TasksPage.1e0zkye4.js.map +0 -9
  84. package/dist/TelemetryPage.p9vbe4gf.js +0 -3
  85. package/dist/TelemetryPage.p9vbe4gf.js.map +0 -9
  86. package/dist/TestsPage.d4xy504e.js +0 -3
  87. package/dist/ThreadsPage.m016am3x.js +0 -3
  88. /package/dist/{App.7fb3e7mp.js.map → App.jdkx6eqd.js.map} +0 -0
  89. /package/dist/{ConnectionsPage.z1pw5xe2.js.map → ConnectionsPage.1dyyfqbk.js.map} +0 -0
  90. /package/dist/{McpPage.8vc97z0b.js.map → McpPage.xvr8hk05.js.map} +0 -0
  91. /package/dist/{SettingsPage.p61bz8kd.js.map → SettingsPage.5jmnefwe.js.map} +0 -0
  92. /package/dist/{SkillsPage.r9x43g3g.js.map → SkillsPage.jw7carjq.js.map} +0 -0
  93. /package/dist/{TestsPage.d4xy504e.js.map → TestsPage.pkymr7yt.js.map} +0 -0
  94. /package/dist/{ThreadsPage.m016am3x.js.map → ThreadsPage.49tgq4fq.js.map} +0 -0
@@ -0,0 +1,4 @@
1
+ import{G as x,H as n,I as r,l as m,q as i}from"./App.jdkx6eqd.js";import{O as j}from"./App.e2kkda2a.js";import{U as D}from"./App.sd685nt9.js";import{$ as t,X as g,aa as u,da as c,ja as V,ma as d}from"./App.shfd8tp9.js";var Q=g(t(),1);var z=g(u(),1);function Zz({onSelectAgent:B}){let{authFetch:N}=V(),{currentProjectId:w}=d(),[L,P]=Q.useState([]),[O,K]=Q.useState(!0),[_,J]=Q.useState("all"),[Z,Y]=Q.useState("all"),[U,W]=Q.useState(null),[R,I]=Q.useState(!1),[$,A]=Q.useState(!1),f=Q.useRef(null),{events:C}=c({category:"TASK"}),v=Q.useCallback(async()=>{try{let G=`/api/tasks?status=${_}`;if(w!==null)G+=`&project_id=${encodeURIComponent(w)}`;let X=await(await N(G)).json();P(X.tasks||[])}catch(G){console.error("Failed to fetch tasks:",G)}finally{K(!1)}},[N,_,w]);Q.useEffect(()=>{v()},[v]),Q.useEffect(()=>{if(!C.length)return;let G=C[0];if(!G||G.id===f.current)return;let H=G.type;if(H==="task_created"||H==="task_updated"||H==="task_deleted")f.current=G.id,console.log("[TasksPage] Telemetry event:",H),v()},[C,v]);let y=Q.useCallback(async(G)=>{W(G),I(!0);try{let H=await N(`/api/tasks/${G.agentId}/${G.id}`);if(console.log("[TasksPage] Fetch task response status:",H.status),H.ok){let X=await H.json();if(console.log("[TasksPage] Task data:",X),console.log("[TasksPage] Has trajectory:",!!X.task?.trajectory,"Length:",X.task?.trajectory?.length),X.task)W({...X.task,agentId:G.agentId,agentName:G.agentName})}else console.error("[TasksPage] Failed to fetch task:",H.status,await H.text())}catch(H){console.error("Failed to fetch task details:",H)}finally{I(!1)}},[N]),b=Q.useMemo(()=>{let G=new Map;for(let H of L){let X=H.agentId||H.agent_id,T=H.agentName||H.agent_name;if(X&&T&&!G.has(X))G.set(X,T)}return Array.from(G.entries()).sort((H,X)=>H[1].localeCompare(X[1]))},[L]),M=Q.useMemo(()=>{return[...Z==="all"?L:L.filter((H)=>(H.agentId||H.agent_id)===Z)].sort((H,X)=>{if(H.status==="running"&&X.status!=="running")return-1;if(X.status==="running"&&H.status!=="running")return 1;let T=H.status==="pending",p=X.status==="pending";if(T&&!p)return-1;if(p&&!T)return 1;if(T&&p||H.status==="running"&&X.status==="running"){let h=H.next_run||H.execute_at||null,l=X.next_run||X.execute_at||null,e=h?new Date(h).getTime():1/0,s=l?new Date(l).getTime():1/0;return e-s}let k=H.completed_at||H.executed_at||H.created_at,a=X.completed_at||X.executed_at||X.created_at;return new Date(a).getTime()-new Date(k).getTime()})},[L,Z]),q={pending:"bg-yellow-500/20 text-yellow-400",running:"bg-blue-500/20 text-blue-400",completed:"bg-green-500/20 text-green-400",failed:"bg-red-500/20 text-red-400",cancelled:"bg-gray-500/20 text-gray-400"};return z.jsxDEV("div",{className:"flex-1 flex overflow-hidden",children:[z.jsxDEV("div",{className:`flex-1 p-4 md:p-6 overflow-auto ${U?"hidden md:block md:w-1/2 lg:w-2/3":""}`,children:z.jsxDEV("div",{className:"max-w-4xl",children:[z.jsxDEV("div",{className:"mb-6",children:[z.jsxDEV("div",{className:"mb-4 flex items-start justify-between",children:[z.jsxDEV("div",{children:[z.jsxDEV("h1",{className:"text-xl md:text-2xl font-semibold mb-1",children:"Tasks"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)]",children:"View tasks from all running agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("button",{onClick:()=>A(!0),className:"px-3 py-1.5 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition flex items-center gap-1.5 flex-shrink-0",children:[z.jsxDEV("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:z.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 4v16m8-8H4"},void 0,!1,void 0,this)},void 0,!1,void 0,this),"Create Task"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex items-center gap-3 flex-wrap pb-1",children:[z.jsxDEV("div",{className:"flex gap-2 overflow-x-auto scrollbar-hide",children:[{value:"all",label:"All"},{value:"pending",label:"Pending"},{value:"running",label:"Running"},{value:"completed",label:"Completed"},{value:"failed",label:"Failed"}].map((G)=>z.jsxDEV("button",{onClick:()=>J(G.value),className:`px-3 py-1.5 rounded text-sm transition whitespace-nowrap ${_===G.value?"bg-[var(--color-accent)] text-black":"bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)]"}`,children:G.label},G.value,!1,void 0,this))},void 0,!1,void 0,this),b.length>0&&z.jsxDEV("div",{className:"w-48",children:z.jsxDEV(D,{value:Z,onChange:Y,placeholder:"All agents",compact:!0,options:[{value:"all",label:"All agents"},...b.map(([G,H])=>({value:G,label:H}))]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O?z.jsxDEV("div",{className:"text-center py-12 text-[var(--color-text-muted)]",children:"Loading tasks..."},void 0,!1,void 0,this):M.length===0?z.jsxDEV("div",{className:"text-center py-12",children:[z.jsxDEV(i,{className:"w-12 h-12 mx-auto mb-4 text-[var(--color-border-light)]"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-[var(--color-text-muted)]",children:"No tasks found"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-faint)] mt-1",children:"Tasks will appear here when agents create them"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):z.jsxDEV("div",{className:"space-y-3",children:M.map((G)=>z.jsxDEV("div",{onClick:()=>y(G),className:`bg-[var(--color-surface)] border rounded-lg p-4 cursor-pointer transition ${U?.id===G.id&&U?.agentId===G.agentId?"border-[var(--color-accent)]":"border-[var(--color-border)] hover:border-[var(--color-border-light)]"}`,children:[z.jsxDEV("div",{className:"flex items-start justify-between mb-2",children:[z.jsxDEV("div",{className:"flex-1",children:[z.jsxDEV("h3",{className:"font-medium",children:G.title},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)]",children:G.agentName},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("span",{className:`px-2 py-1 rounded text-xs font-medium ${q[G.status]||q.pending}`,children:G.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G.description&&z.jsxDEV("p",{className:"text-sm text-[var(--color-text-secondary)] mb-2 line-clamp-2",children:G.description},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-[var(--color-text-faint)]",children:[z.jsxDEV("span",{className:"flex items-center gap-1",children:[G.type==="recurring"?z.jsxDEV(x,{className:"w-3.5 h-3.5"},void 0,!1,void 0,this):G.execute_at?z.jsxDEV(n,{className:"w-3.5 h-3.5"},void 0,!1,void 0,this):z.jsxDEV(r,{className:"w-3.5 h-3.5"},void 0,!1,void 0,this),G.type==="recurring"&&G.recurrence?E(G.recurrence):G.type]},void 0,!0,void 0,this),z.jsxDEV("span",{children:["Priority: ",G.priority]},void 0,!0,void 0,this),G.next_run&&z.jsxDEV("span",{className:"text-[var(--color-accent)]",children:F(G.next_run)},void 0,!1,void 0,this),!G.next_run&&G.execute_at&&z.jsxDEV("span",{className:"text-[var(--color-accent)]",children:F(G.execute_at)},void 0,!1,void 0,this),z.jsxDEV("span",{children:["Created: ",new Date(G.created_at).toLocaleDateString()]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},`${G.agentId}-${G.id}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),U&&z.jsxDEV(zz,{task:U,statusColors:q,onClose:()=>W(null),onSelectAgent:B,loading:R,authFetch:N,onRefresh:()=>{v(),W(null)}},void 0,!1,void 0,this),$&&z.jsxDEV(Gz,{authFetch:N,currentProjectId:w,onClose:()=>A(!1),onCreated:()=>{v(),A(!1)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function zz({task:B,statusColors:N,onClose:w,onSelectAgent:L,loading:P,authFetch:O,onRefresh:K}){let[_,J]=Q.useState(!1),[Z,Y]=Q.useState(!1),[U,W]=Q.useState(!1),[R,I]=Q.useState(!1),[$,A]=Q.useState({title:B.title,description:B.description||"",type:B.type,priority:B.priority,execute_at:B.execute_at?new Date(B.execute_at).toISOString().slice(0,16):"",recurrence:B.recurrence||""}),{confirm:f,ConfirmDialog:C}=j();Q.useEffect(()=>{A({title:B.title,description:B.description||"",type:B.type,priority:B.priority,execute_at:B.execute_at?new Date(B.execute_at).toISOString().slice(0,16):"",recurrence:B.recurrence||""}),W(!1)},[B.id,B.agentId]);let v=async()=>{if(!O||R)return;I(!0);try{let q={title:$.title.trim(),description:$.description.trim()||void 0,type:$.type,priority:$.priority};if($.type==="once"&&$.execute_at)q.execute_at=new Date($.execute_at).toISOString();if($.type==="recurring"&&$.recurrence.trim())q.recurrence=$.recurrence.trim();if((await O(`/api/tasks/${B.agentId}/${B.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(q)})).ok)W(!1),K?.()}catch(q){console.error("Failed to update task:",q)}finally{I(!1)}},y=async()=>{if(!O||_)return;J(!0);try{await O(`/api/tasks/${B.agentId}/${B.id}/execute`,{method:"POST"}),K?.()}catch(q){console.error("Failed to execute task:",q)}finally{J(!1)}},b=async()=>{if(!O||Z)return;if(!await f(`Are you sure you want to delete "${B.title}"?`,{title:"Delete Task",confirmText:"Delete",confirmVariant:"danger"}))return;Y(!0);try{await O(`/api/tasks/${B.agentId}/${B.id}`,{method:"DELETE"}),K?.()}catch(S){console.error("Failed to delete task:",S)}finally{Y(!1)}},M="w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-2 py-1.5 text-sm focus:outline-none focus:border-[var(--color-accent)] text-[var(--color-text)]";return z.jsxDEV("div",{className:"w-full md:w-1/2 lg:w-1/3 border-l border-[var(--color-border)] bg-[var(--color-bg)] flex flex-col overflow-hidden",children:[C,z.jsxDEV("div",{className:"flex items-center justify-between p-4 border-b border-[var(--color-border)]",children:[z.jsxDEV("h2",{className:"font-medium truncate pr-2",children:U?"Edit Task":"Task Details"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex items-center gap-2",children:[O&&!U&&(B.status==="pending"||B.status==="completed"||B.status==="failed")&&z.jsxDEV("button",{onClick:()=>W(!0),title:"Edit task",className:"text-[var(--color-text-muted)] hover:text-[var(--color-accent)] transition",children:z.jsxDEV("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:z.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),O&&!U&&(B.status==="pending"||B.status==="completed")&&z.jsxDEV("button",{onClick:y,disabled:_,title:"Execute now",className:"text-[var(--color-accent)] hover:opacity-80 transition disabled:opacity-50",children:z.jsxDEV("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[z.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"},void 0,!1,void 0,this),z.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M21 12a9 9 0 11-18 0 9 9 0 0118 0z"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),O&&!U&&z.jsxDEV("button",{onClick:b,disabled:Z,title:"Delete task",className:"text-red-400 hover:text-red-300 transition disabled:opacity-50",children:z.jsxDEV("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:z.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),U&&z.jsxDEV(z.Fragment,{children:[z.jsxDEV("button",{onClick:()=>{W(!1),A({title:B.title,description:B.description||"",type:B.type,priority:B.priority,execute_at:B.execute_at?new Date(B.execute_at).toISOString().slice(0,16):"",recurrence:B.recurrence||""})},className:"text-[var(--color-text-muted)] hover:text-[var(--color-text)] text-sm transition",children:"Cancel"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:v,disabled:R||!$.title.trim(),className:"px-3 py-1 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition disabled:opacity-50",children:R?"Saving...":"Save"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),!U&&z.jsxDEV("button",{onClick:w,className:"text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition",children:z.jsxDEV(m,{},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex-1 overflow-auto p-4 space-y-4",children:[z.jsxDEV("div",{children:[z.jsxDEV("div",{className:"flex items-start justify-between gap-2 mb-2",children:[U?z.jsxDEV("input",{type:"text",value:$.title,onChange:(q)=>A({...$,title:q.target.value}),className:`${M} text-lg font-medium`,placeholder:"Task title"},void 0,!1,void 0,this):z.jsxDEV("h3",{className:"text-lg font-medium",children:B.title},void 0,!1,void 0,this),!U&&z.jsxDEV("span",{className:`px-2 py-1 rounded text-xs font-medium flex-shrink-0 ${N[B.status]}`,children:B.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this),!U&&z.jsxDEV("button",{onClick:()=>L?.(B.agentId),className:"text-sm text-[var(--color-accent)] hover:underline",children:B.agentName},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U?z.jsxDEV("div",{children:[z.jsxDEV("h4",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1",children:"Description"},void 0,!1,void 0,this),z.jsxDEV("textarea",{value:$.description,onChange:(q)=>A({...$,description:q.target.value}),className:`${M} resize-none`,rows:3,placeholder:"Task description..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this):B.description?z.jsxDEV("div",{children:[z.jsxDEV("h4",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1",children:"Description"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-secondary)] whitespace-pre-wrap",children:B.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null,U?z.jsxDEV("div",{className:"grid grid-cols-2 gap-3",children:[z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block",children:"Type"},void 0,!1,void 0,this),z.jsxDEV("select",{value:$.type,onChange:(q)=>A({...$,type:q.target.value}),className:M,children:[z.jsxDEV("option",{value:"once",children:"One-time"},void 0,!1,void 0,this),z.jsxDEV("option",{value:"recurring",children:"Recurring"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block",children:"Priority"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"number",min:1,max:10,value:$.priority,onChange:(q)=>A({...$,priority:Number(q.target.value)}),className:M},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):z.jsxDEV("div",{className:"grid grid-cols-2 gap-3 text-sm",children:[z.jsxDEV("div",{children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Type"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"capitalize",children:B.type},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Priority"},void 0,!1,void 0,this),z.jsxDEV("p",{children:B.priority},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Source"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"capitalize",children:B.source},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.recurrence&&z.jsxDEV("div",{children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Recurrence"},void 0,!1,void 0,this),z.jsxDEV("p",{children:E(B.recurrence)},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-0.5 font-mono",children:B.recurrence},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U&&$.type==="once"&&z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block",children:"Schedule"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"datetime-local",value:$.execute_at,onChange:(q)=>A({...$,execute_at:q.target.value}),className:M},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"Leave empty for manual execution"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U&&$.type==="recurring"&&z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block",children:"Cron Schedule"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"text",value:$.recurrence,onChange:(q)=>A({...$,recurrence:q.target.value}),className:`${M} font-mono`,placeholder:"*/30 * * * *"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"e.g. */30 * * * * = every 30 min"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),!U&&z.jsxDEV("div",{className:"space-y-2 text-sm",children:[z.jsxDEV("div",{className:"flex justify-between",children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Created"},void 0,!1,void 0,this),z.jsxDEV("span",{children:new Date(B.created_at).toLocaleString()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.execute_at&&z.jsxDEV("div",{className:"flex justify-between",children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Scheduled"},void 0,!1,void 0,this),z.jsxDEV("span",{className:"text-[var(--color-accent)]",children:F(B.execute_at)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.executed_at&&z.jsxDEV("div",{className:"flex justify-between",children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Started"},void 0,!1,void 0,this),z.jsxDEV("span",{children:new Date(B.executed_at).toLocaleString()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.completed_at&&z.jsxDEV("div",{className:"flex justify-between",children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Completed"},void 0,!1,void 0,this),z.jsxDEV("span",{children:new Date(B.completed_at).toLocaleString()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.next_run&&z.jsxDEV("div",{className:"flex justify-between",children:[z.jsxDEV("span",{className:"text-[var(--color-text-muted)]",children:"Next Run"},void 0,!1,void 0,this),z.jsxDEV("span",{className:"text-[var(--color-accent)]",children:F(B.next_run)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),B.status==="failed"&&B.error&&z.jsxDEV("div",{className:"min-w-0",children:[z.jsxDEV("h4",{className:"text-xs text-red-400 uppercase tracking-wider mb-1",children:"Error"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"bg-red-500/10 border border-red-500/20 rounded p-3 overflow-x-auto",children:z.jsxDEV("pre",{className:"text-sm text-red-400 whitespace-pre-wrap break-words",children:B.error},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.status==="completed"&&B.result&&z.jsxDEV("div",{className:"min-w-0",children:[z.jsxDEV("h4",{className:"text-xs text-green-400 uppercase tracking-wider mb-1",children:"Result"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"bg-green-500/10 border border-green-500/20 rounded p-3 overflow-x-auto",children:z.jsxDEV("pre",{className:"text-sm text-green-400 whitespace-pre-wrap break-words",children:typeof B.result==="string"?B.result:JSON.stringify(B.result,null,2)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P&&!B.trajectory&&z.jsxDEV("div",{children:[z.jsxDEV("h4",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-2",children:"Trajectory"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"text-sm text-[var(--color-text-faint)]",children:"Loading trajectory..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.trajectory&&B.trajectory.length>0&&z.jsxDEV("div",{children:[z.jsxDEV("h4",{className:"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-2",children:["Trajectory (",B.trajectory.length," steps)"]},void 0,!0,void 0,this),z.jsxDEV(Bz,{trajectory:B.trajectory},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 Bz({trajectory:B}){let[N,w]=Q.useState(new Set),L=(K)=>{w((_)=>{let J=new Set(_);if(J.has(K))J.delete(K);else J.add(K);return J})},P={user:{bg:"bg-blue-500/10",text:"text-blue-400",icon:"\uD83D\uDC64",label:"User"},assistant:{bg:"bg-purple-500/10",text:"text-purple-400",icon:"\uD83E\uDD16",label:"Assistant"}},O=(K)=>{let _=K.content;if(typeof _==="string"){let J=_.length>200,Z=N.has(K.id);return z.jsxDEV("div",{children:[z.jsxDEV("p",{className:`text-sm text-[var(--color-text)] whitespace-pre-wrap break-words ${!Z&&J?"line-clamp-4":""}`,children:_},void 0,!1,void 0,this),J&&z.jsxDEV("button",{onClick:()=>L(K.id),className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1",children:Z?"Show less":"Show more..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}return z.jsxDEV("div",{className:"space-y-2",children:_.map((J,Z)=>{if(J.type==="tool_use"){let Y=JSON.stringify(J.input,null,2),U=Y.length>150,W=`${K.id}-${Z}`,R=N.has(W);return z.jsxDEV("div",{className:"bg-orange-500/10 border border-orange-500/20 rounded p-2",children:[z.jsxDEV("div",{className:"flex items-center gap-2 mb-1",children:[z.jsxDEV("span",{className:"text-orange-400",children:"\uD83D\uDD27"},void 0,!1,void 0,this),z.jsxDEV("span",{className:"text-xs font-medium text-orange-400",children:"Tool Call"},void 0,!1,void 0,this),z.jsxDEV("span",{className:"text-xs text-[var(--color-text-secondary)]",children:J.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("pre",{className:`text-xs text-[var(--color-text-secondary)] overflow-x-auto ${!R&&U?"line-clamp-3":""}`,children:Y},void 0,!1,void 0,this),U&&z.jsxDEV("button",{onClick:()=>L(W),className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1",children:R?"Show less":"Show more..."},void 0,!1,void 0,this)]},Z,!0,void 0,this)}if(J.type==="tool_result"){let Y=J.is_error,U=`${K.id}-${Z}`,W=N.has(U),R=J.content.length>150;return z.jsxDEV("div",{className:`${Y?"bg-red-500/10 border-red-500/20":"bg-teal-500/10 border-teal-500/20"} border rounded p-2`,children:[z.jsxDEV("div",{className:"flex items-center gap-2 mb-1",children:[z.jsxDEV("span",{children:Y?"❌":"\uD83D\uDCCB"},void 0,!1,void 0,this),z.jsxDEV("span",{className:`text-xs font-medium ${Y?"text-red-400":"text-teal-400"}`,children:"Tool Result"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("pre",{className:`text-xs text-[var(--color-text-secondary)] overflow-x-auto whitespace-pre-wrap break-words ${!W&&R?"line-clamp-3":""}`,children:J.content},void 0,!1,void 0,this),R&&z.jsxDEV("button",{onClick:()=>L(U),className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1",children:W?"Show less":"Show more..."},void 0,!1,void 0,this)]},Z,!0,void 0,this)}return null})},void 0,!1,void 0,this)};return z.jsxDEV("div",{className:"space-y-2",children:B.map((K)=>{let _=P[K.role]||P.assistant;return z.jsxDEV("div",{className:`${_.bg} border border-[var(--color-border)] rounded overflow-hidden p-3`,children:[z.jsxDEV("div",{className:"flex items-center gap-2 mb-2",children:[z.jsxDEV("span",{children:_.icon},void 0,!1,void 0,this),z.jsxDEV("span",{className:`text-xs font-medium ${_.text}`,children:_.label},void 0,!1,void 0,this),K.model&&z.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)]",children:["· ",K.model]},void 0,!0,void 0,this),z.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)]",children:["· ",new Date(K.created_at).toLocaleTimeString()]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O(K)]},K.id,!0,void 0,this)})},void 0,!1,void 0,this)}function Gz({authFetch:B,currentProjectId:N,onClose:w,onCreated:L}){let[P,O]=Q.useState([]),[K,_]=Q.useState(""),[J,Z]=Q.useState(""),[Y,U]=Q.useState(""),[W,R]=Q.useState("once"),[I,$]=Q.useState(5),[A,f]=Q.useState(""),[C,v]=Q.useState(""),[y,b]=Q.useState(!1),[M,q]=Q.useState("");return Q.useEffect(()=>{B("/api/agents").then((G)=>G.json()).then((G)=>{let H=(G.agents||[]).filter((X)=>X.status==="running"&&X.features?.tasks);if(O(H.map((X)=>({id:X.id,name:X.name}))),H.length===1)_(H[0].id)}).catch(()=>{})},[B]),z.jsxDEV("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",onClick:w,children:z.jsxDEV("div",{className:"bg-[var(--color-surface)] card w-full max-w-md",onClick:(G)=>G.stopPropagation(),children:[z.jsxDEV("div",{className:"flex items-center justify-between p-4 border-b border-[var(--color-border)]",children:[z.jsxDEV("h2",{className:"font-medium",children:"Create Task"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:w,className:"text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition",children:z.jsxDEV(m,{},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("form",{onSubmit:async(G)=>{if(G.preventDefault(),!K||!J.trim())return;b(!0),q("");let H={title:J.trim(),description:Y.trim()||void 0,type:W,priority:I};if(W==="once"&&A)H.execute_at=new Date(A).toISOString();if(W==="recurring"&&C.trim())H.recurrence=C.trim();try{let X=await B(`/api/tasks/${K}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(H)});if(!X.ok){let T=await X.json().catch(()=>({}));q(T.error||`HTTP ${X.status}`);return}L()}catch(X){q(String(X))}finally{b(!1)}},className:"p-4 space-y-4",children:[z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Agent"},void 0,!1,void 0,this),P.length===0?z.jsxDEV("p",{className:"text-sm text-[var(--color-text-faint)]",children:"No running agents with tasks enabled"},void 0,!1,void 0,this):z.jsxDEV("select",{value:K,onChange:(G)=>_(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm",required:!0,children:[z.jsxDEV("option",{value:"",children:"Select agent..."},void 0,!1,void 0,this),P.map((G)=>z.jsxDEV("option",{value:G.id,children:G.name},G.id,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Title"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"text",value:J,onChange:(G)=>Z(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm",placeholder:"e.g. Check email for new orders",required:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Description"},void 0,!1,void 0,this),z.jsxDEV("textarea",{value:Y,onChange:(G)=>U(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm resize-none",rows:2,placeholder:"Optional instructions for the agent..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"grid grid-cols-2 gap-3",children:[z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Type"},void 0,!1,void 0,this),z.jsxDEV("select",{value:W,onChange:(G)=>R(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm",children:[z.jsxDEV("option",{value:"once",children:"One-time"},void 0,!1,void 0,this),z.jsxDEV("option",{value:"recurring",children:"Recurring"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Priority"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"number",min:1,max:10,value:I,onChange:(G)=>$(Number(G.target.value)),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),W==="once"&&z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Schedule (optional)"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"datetime-local",value:A,onChange:(G)=>f(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"Leave empty to execute immediately"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),W==="recurring"&&z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-muted)] mb-1",children:"Cron Schedule"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"text",value:C,onChange:(G)=>v(G.target.value),className:"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm font-mono",placeholder:"*/30 * * * *",required:!0},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"e.g. */30 * * * * = every 30 min, 0 9 * * 1-5 = weekdays at 9am"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M&&z.jsxDEV("p",{className:"text-sm text-red-400",children:M},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex justify-end gap-2 pt-2",children:[z.jsxDEV("button",{type:"button",onClick:w,className:"px-4 py-2 rounded text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-border)] transition",children:"Cancel"},void 0,!1,void 0,this),z.jsxDEV("button",{type:"submit",disabled:y||!K||!J.trim()||P.length===0,className:"px-4 py-2 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition disabled:opacity-50",children:y?"Creating...":"Create Task"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function E(B){try{let N=B.trim().split(/\s+/);if(N.length!==5)return B;let[w,L,P,O,K]=N;if(w.startsWith("*/")&&L==="*"&&P==="*"&&O==="*"&&K==="*"){let J=parseInt(w.slice(2));if(J===1)return"Every minute";return`Every ${J} minutes`}if(w!=="*"&&!w.includes("/")&&L==="*"&&P==="*"&&O==="*"&&K==="*")return"Every hour";if(L.startsWith("*/")&&P==="*"&&O==="*"&&K==="*"){let J=parseInt(L.slice(2));if(J===1)return"Every hour";return`Every ${J} hours`}let _=(J,Z)=>{let Y=parseInt(J),U=parseInt(Z);if(isNaN(Y))return"";let W=Y>=12?"PM":"AM";return`${Y===0?12:Y>12?Y-12:Y}:${U.toString().padStart(2,"0")} ${W}`};if(L!=="*"&&!L.includes("/")&&P==="*"&&O==="*"){let J=_(L,w);if(K==="*")return`Daily at ${J}`;let Z=K.split(",").map((Y)=>{let U=parseInt(Y.trim());return o[U]||Y});if(Z.length===7)return`Daily at ${J}`;if(Z.length===5&&!Z.includes("Sat")&&!Z.includes("Sun"))return`Weekdays at ${J}`;if(Z.length===1)return`Weekly on ${Z[0]} at ${J}`;return`${Z.join(" & ")} at ${J}`}return B}catch{return B}}function F(B){let N=new Date(B),w=new Date,L=N.getTime()-w.getTime(),P=Math.abs(L),O=L>0,K=Math.floor(P/60000),_=Math.floor(P/3600000),J=Math.floor(P/86400000),Z=N.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),Y=N.toDateString()===w.toDateString(),U=new Date(w);U.setDate(U.getDate()+1);let W=N.toDateString()===U.toDateString(),R=new Date(w);R.setDate(R.getDate()-1);let I=N.toDateString()===R.toDateString();if(Y){if(K<1)return O?"now":"just now";if(K<60)return O?`in ${K} min (${Z})`:`${K} min ago`;return O?`in ${_}h (${Z})`:`${_}h ago`}if(W)return`Tomorrow at ${Z}`;if(I)return`Yesterday at ${Z}`;if(J<7)return`${o[N.getDay()]} at ${Z}`;return N.toLocaleDateString([],{month:"short",day:"numeric"})+` at ${Z}`}
2
+ export{Zz as d,zz as e,Bz as f,E as g,F as h};
3
+
4
+ //# debugId=8E2D9B056A9C318964756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/tasks/TasksPage.tsx"],
4
+ "sourcesContent": [
5
+ "import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { TasksIcon, CloseIcon, RecurringIcon, ScheduledIcon, TaskOnceIcon } from \"../common/Icons\";\nimport { Select } from \"../common/Select\";\nimport { useConfirm } from \"../common/Modal\";\nimport { useAuth, useProjects } from \"../../context\";\nimport { useTelemetry } from \"../../context/TelemetryContext\";\nimport type { Task, TaskTrajectoryStep, ToolUseBlock, ToolResultBlock, Agent } from \"../../types\";\n\ninterface TasksPageProps {\n onSelectAgent?: (agentId: string) => void;\n}\n\nexport function TasksPage({ onSelectAgent }: TasksPageProps) {\n const { authFetch } = useAuth();\n const { currentProjectId } = useProjects();\n const [tasks, setTasks] = useState<Task[]>([]);\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState<string>(\"all\");\n const [agentFilter, setAgentFilter] = useState<string>(\"all\");\n const [selectedTask, setSelectedTask] = useState<Task | null>(null);\n const [loadingTask, setLoadingTask] = useState(false);\n const [showCreateModal, setShowCreateModal] = useState(false);\n const lastProcessedEventRef = useRef<string | null>(null);\n\n // Subscribe to task telemetry events for real-time updates\n const { events: taskEvents } = useTelemetry({ category: \"TASK\" });\n\n const fetchTasks = useCallback(async () => {\n try {\n let url = `/api/tasks?status=${filter}`;\n if (currentProjectId !== null) {\n url += `&project_id=${encodeURIComponent(currentProjectId)}`;\n }\n const res = await authFetch(url);\n const data = await res.json();\n setTasks(data.tasks || []);\n } catch (e) {\n console.error(\"Failed to fetch tasks:\", e);\n } finally {\n setLoading(false);\n }\n }, [authFetch, filter, currentProjectId]);\n\n // Initial fetch\n useEffect(() => {\n fetchTasks();\n }, [fetchTasks]);\n\n // Handle real-time task events from telemetry - use as trigger to refetch\n // since telemetry data is incomplete (missing id, agentId, status, etc.)\n useEffect(() => {\n if (!taskEvents.length) return;\n\n const latestEvent = taskEvents[0];\n if (!latestEvent || latestEvent.id === lastProcessedEventRef.current) return;\n\n // Only react to task mutation events\n const eventType = latestEvent.type;\n if (eventType === \"task_created\" || eventType === \"task_updated\" || eventType === \"task_deleted\") {\n lastProcessedEventRef.current = latestEvent.id;\n console.log(\"[TasksPage] Telemetry event:\", eventType);\n // Refetch to get complete task data\n fetchTasks();\n }\n }, [taskEvents, fetchTasks]);\n\n // Fetch full task details (including trajectory) when selecting a task\n const selectTask = useCallback(async (task: Task) => {\n // Set task immediately for quick feedback\n setSelectedTask(task);\n setLoadingTask(true);\n\n try {\n const res = await authFetch(`/api/tasks/${task.agentId}/${task.id}`);\n console.log(\"[TasksPage] Fetch task response status:\", res.status);\n if (res.ok) {\n const data = await res.json();\n console.log(\"[TasksPage] Task data:\", data);\n console.log(\"[TasksPage] Has trajectory:\", !!data.task?.trajectory, \"Length:\", data.task?.trajectory?.length);\n if (data.task) {\n // Merge with agentId/agentName since API might not include them\n setSelectedTask({ ...data.task, agentId: task.agentId, agentName: task.agentName });\n }\n } else {\n console.error(\"[TasksPage] Failed to fetch task:\", res.status, await res.text());\n }\n } catch (e) {\n console.error(\"Failed to fetch task details:\", e);\n } finally {\n setLoadingTask(false);\n }\n }, [authFetch]);\n\n // Extract unique agents from tasks for the agent filter\n const uniqueAgents = useMemo(() => {\n const map = new Map<string, string>();\n for (const t of tasks) {\n const id = t.agentId || (t as any).agent_id;\n const name = t.agentName || (t as any).agent_name;\n if (id && name && !map.has(id)) {\n map.set(id, name);\n }\n }\n return Array.from(map.entries()).sort((a, b) => a[1].localeCompare(b[1]));\n }, [tasks]);\n\n // Sort tasks: running first, then pending by next execution (soonest first), then completed/failed by date\n const sortedTasks = useMemo(() => {\n const filtered = agentFilter === \"all\" ? tasks : tasks.filter(t => (t.agentId || (t as any).agent_id) === agentFilter);\n return [...filtered].sort((a, b) => {\n // Running tasks first\n if (a.status === \"running\" && b.status !== \"running\") return -1;\n if (b.status === \"running\" && a.status !== \"running\") return 1;\n // Pending tasks next\n const aIsPending = a.status === \"pending\";\n const bIsPending = b.status === \"pending\";\n if (aIsPending && !bIsPending) return -1;\n if (bIsPending && !aIsPending) return 1;\n // For running/pending: sort by next execution time (soonest first)\n if (aIsPending && bIsPending || a.status === \"running\" && b.status === \"running\") {\n const aTime = a.next_run || a.execute_at || null;\n const bTime = b.next_run || b.execute_at || null;\n const aTs = aTime ? new Date(aTime).getTime() : Infinity;\n const bTs = bTime ? new Date(bTime).getTime() : Infinity;\n return aTs - bTs;\n }\n // For completed/failed: most recent first\n const aDate = a.completed_at || a.executed_at || a.created_at;\n const bDate = b.completed_at || b.executed_at || b.created_at;\n return new Date(bDate).getTime() - new Date(aDate).getTime();\n });\n }, [tasks, agentFilter]);\n\n const statusColors: Record<string, string> = {\n pending: \"bg-yellow-500/20 text-yellow-400\",\n running: \"bg-blue-500/20 text-blue-400\",\n completed: \"bg-green-500/20 text-green-400\",\n failed: \"bg-red-500/20 text-red-400\",\n cancelled: \"bg-gray-500/20 text-gray-400\",\n };\n\n const filterOptions = [\n { value: \"all\", label: \"All\" },\n { value: \"pending\", label: \"Pending\" },\n { value: \"running\", label: \"Running\" },\n { value: \"completed\", label: \"Completed\" },\n { value: \"failed\", label: \"Failed\" },\n ];\n\n return (\n <div className=\"flex-1 flex overflow-hidden\">\n {/* Task List */}\n <div className={`flex-1 p-4 md:p-6 overflow-auto ${selectedTask ? 'hidden md:block md:w-1/2 lg:w-2/3' : ''}`}>\n <div className=\"max-w-4xl\">\n <div className=\"mb-6\">\n <div className=\"mb-4 flex items-start justify-between\">\n <div>\n <h1 className=\"text-xl md:text-2xl font-semibold mb-1\">Tasks</h1>\n <p className=\"text-sm text-[var(--color-text-muted)]\">\n View tasks from all running agents\n </p>\n </div>\n <button\n onClick={() => setShowCreateModal(true)}\n className=\"px-3 py-1.5 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition flex items-center gap-1.5 flex-shrink-0\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" /></svg>\n Create Task\n </button>\n </div>\n <div className=\"flex items-center gap-3 flex-wrap pb-1\">\n <div className=\"flex gap-2 overflow-x-auto scrollbar-hide\">\n {filterOptions.map(opt => (\n <button\n key={opt.value}\n onClick={() => setFilter(opt.value)}\n className={`px-3 py-1.5 rounded text-sm transition whitespace-nowrap ${\n filter === opt.value\n ? \"bg-[var(--color-accent)] text-black\"\n : \"bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)]\"\n }`}\n >\n {opt.label}\n </button>\n ))}\n </div>\n {uniqueAgents.length > 0 && (\n <div className=\"w-48\">\n <Select\n value={agentFilter}\n onChange={setAgentFilter}\n placeholder=\"All agents\"\n compact\n options={[\n { value: \"all\", label: \"All agents\" },\n ...uniqueAgents.map(([id, name]) => ({ value: id, label: name })),\n ]}\n />\n </div>\n )}\n </div>\n </div>\n\n {loading ? (\n <div className=\"text-center py-12 text-[var(--color-text-muted)]\">Loading tasks...</div>\n ) : sortedTasks.length === 0 ? (\n <div className=\"text-center py-12\">\n <TasksIcon className=\"w-12 h-12 mx-auto mb-4 text-[var(--color-border-light)]\" />\n <p className=\"text-[var(--color-text-muted)]\">No tasks found</p>\n <p className=\"text-sm text-[var(--color-text-faint)] mt-1\">\n Tasks will appear here when agents create them\n </p>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {sortedTasks.map(task => (\n <div\n key={`${task.agentId}-${task.id}`}\n onClick={() => selectTask(task)}\n className={`bg-[var(--color-surface)] border rounded-lg p-4 cursor-pointer transition ${\n selectedTask?.id === task.id && selectedTask?.agentId === task.agentId\n ? \"border-[var(--color-accent)]\"\n : \"border-[var(--color-border)] hover:border-[var(--color-border-light)]\"\n }`}\n >\n <div className=\"flex items-start justify-between mb-2\">\n <div className=\"flex-1\">\n <h3 className=\"font-medium\">{task.title}</h3>\n <p className=\"text-sm text-[var(--color-text-muted)]\">{task.agentName}</p>\n </div>\n <span className={`px-2 py-1 rounded text-xs font-medium ${statusColors[task.status] || statusColors.pending}`}>\n {task.status}\n </span>\n </div>\n\n {task.description && (\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-2 line-clamp-2\">\n {task.description}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-[var(--color-text-faint)]\">\n <span className=\"flex items-center gap-1\">\n {task.type === \"recurring\"\n ? <RecurringIcon className=\"w-3.5 h-3.5\" />\n : task.execute_at\n ? <ScheduledIcon className=\"w-3.5 h-3.5\" />\n : <TaskOnceIcon className=\"w-3.5 h-3.5\" />\n }\n {task.type === \"recurring\" && task.recurrence ? formatCron(task.recurrence) : task.type}\n </span>\n <span>Priority: {task.priority}</span>\n {task.next_run && (\n <span className=\"text-[var(--color-accent)]\">{formatRelativeTime(task.next_run)}</span>\n )}\n {!task.next_run && task.execute_at && (\n <span className=\"text-[var(--color-accent)]\">{formatRelativeTime(task.execute_at)}</span>\n )}\n <span>Created: {new Date(task.created_at).toLocaleDateString()}</span>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Task Detail Panel */}\n {selectedTask && (\n <TaskDetailPanel\n task={selectedTask}\n statusColors={statusColors}\n onClose={() => setSelectedTask(null)}\n onSelectAgent={onSelectAgent}\n loading={loadingTask}\n authFetch={authFetch}\n onRefresh={() => { fetchTasks(); setSelectedTask(null); }}\n />\n )}\n\n {/* Create Task Modal */}\n {showCreateModal && (\n <CreateTaskModal\n authFetch={authFetch}\n currentProjectId={currentProjectId}\n onClose={() => setShowCreateModal(false)}\n onCreated={() => { fetchTasks(); setShowCreateModal(false); }}\n />\n )}\n </div>\n );\n}\n\nexport interface TaskDetailPanelProps {\n task: Task;\n statusColors: Record<string, string>;\n onClose: () => void;\n onSelectAgent?: (agentId: string) => void;\n loading?: boolean;\n authFetch?: (url: string, options?: RequestInit) => Promise<Response>;\n onRefresh?: () => void;\n}\n\nexport function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, loading, authFetch, onRefresh }: TaskDetailPanelProps) {\n const [executing, setExecuting] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [editing, setEditing] = useState(false);\n const [saving, setSaving] = useState(false);\n const [editForm, setEditForm] = useState({\n title: task.title,\n description: task.description || \"\",\n type: task.type as \"once\" | \"recurring\",\n priority: task.priority,\n execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : \"\",\n recurrence: task.recurrence || \"\",\n });\n const { confirm, ConfirmDialog } = useConfirm();\n\n // Reset edit form when task changes\n useEffect(() => {\n setEditForm({\n title: task.title,\n description: task.description || \"\",\n type: task.type as \"once\" | \"recurring\",\n priority: task.priority,\n execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : \"\",\n recurrence: task.recurrence || \"\",\n });\n setEditing(false);\n }, [task.id, task.agentId]);\n\n const handleSave = async () => {\n if (!authFetch || saving) return;\n setSaving(true);\n try {\n const body: Record<string, unknown> = {\n title: editForm.title.trim(),\n description: editForm.description.trim() || undefined,\n type: editForm.type,\n priority: editForm.priority,\n };\n if (editForm.type === \"once\" && editForm.execute_at) {\n body.execute_at = new Date(editForm.execute_at).toISOString();\n }\n if (editForm.type === \"recurring\" && editForm.recurrence.trim()) {\n body.recurrence = editForm.recurrence.trim();\n }\n const res = await authFetch(`/api/tasks/${task.agentId}/${task.id}`, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (res.ok) {\n setEditing(false);\n onRefresh?.();\n }\n } catch (e) {\n console.error(\"Failed to update task:\", e);\n } finally {\n setSaving(false);\n }\n };\n\n const handleExecute = async () => {\n if (!authFetch || executing) return;\n setExecuting(true);\n try {\n await authFetch(`/api/tasks/${task.agentId}/${task.id}/execute`, { method: \"POST\" });\n onRefresh?.();\n } catch (e) {\n console.error(\"Failed to execute task:\", e);\n } finally {\n setExecuting(false);\n }\n };\n\n const handleDelete = async () => {\n if (!authFetch || deleting) return;\n const ok = await confirm(`Are you sure you want to delete \"${task.title}\"?`, {\n title: \"Delete Task\",\n confirmText: \"Delete\",\n confirmVariant: \"danger\",\n });\n if (!ok) return;\n setDeleting(true);\n try {\n await authFetch(`/api/tasks/${task.agentId}/${task.id}`, { method: \"DELETE\" });\n onRefresh?.();\n } catch (e) {\n console.error(\"Failed to delete task:\", e);\n } finally {\n setDeleting(false);\n }\n };\n\n const inputClass = \"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-2 py-1.5 text-sm focus:outline-none focus:border-[var(--color-accent)] text-[var(--color-text)]\";\n\n return (\n <div className=\"w-full md:w-1/2 lg:w-1/3 border-l border-[var(--color-border)] bg-[var(--color-bg)] flex flex-col overflow-hidden\">\n {ConfirmDialog}\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--color-border)]\">\n <h2 className=\"font-medium truncate pr-2\">{editing ? \"Edit Task\" : \"Task Details\"}</h2>\n <div className=\"flex items-center gap-2\">\n {authFetch && !editing && (task.status === \"pending\" || task.status === \"completed\" || task.status === \"failed\") && (\n <button\n onClick={() => setEditing(true)}\n title=\"Edit task\"\n className=\"text-[var(--color-text-muted)] hover:text-[var(--color-accent)] transition\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\" /></svg>\n </button>\n )}\n {authFetch && !editing && (task.status === \"pending\" || task.status === \"completed\") && (\n <button\n onClick={handleExecute}\n disabled={executing}\n title=\"Execute now\"\n className=\"text-[var(--color-accent)] hover:opacity-80 transition disabled:opacity-50\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\" /><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" /></svg>\n </button>\n )}\n {authFetch && !editing && (\n <button\n onClick={handleDelete}\n disabled={deleting}\n title=\"Delete task\"\n className=\"text-red-400 hover:text-red-300 transition disabled:opacity-50\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" /></svg>\n </button>\n )}\n {editing && (\n <>\n <button\n onClick={() => {\n setEditing(false);\n setEditForm({\n title: task.title,\n description: task.description || \"\",\n type: task.type as \"once\" | \"recurring\",\n priority: task.priority,\n execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : \"\",\n recurrence: task.recurrence || \"\",\n });\n }}\n className=\"text-[var(--color-text-muted)] hover:text-[var(--color-text)] text-sm transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={saving || !editForm.title.trim()}\n className=\"px-3 py-1 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition disabled:opacity-50\"\n >\n {saving ? \"Saving...\" : \"Save\"}\n </button>\n </>\n )}\n {!editing && (\n <button onClick={onClose} className=\"text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition\">\n <CloseIcon />\n </button>\n )}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {/* Title & Status */}\n <div>\n <div className=\"flex items-start justify-between gap-2 mb-2\">\n {editing ? (\n <input\n type=\"text\"\n value={editForm.title}\n onChange={e => setEditForm({ ...editForm, title: e.target.value })}\n className={`${inputClass} text-lg font-medium`}\n placeholder=\"Task title\"\n />\n ) : (\n <h3 className=\"text-lg font-medium\">{task.title}</h3>\n )}\n {!editing && (\n <span className={`px-2 py-1 rounded text-xs font-medium flex-shrink-0 ${statusColors[task.status]}`}>\n {task.status}\n </span>\n )}\n </div>\n {!editing && (\n <button\n onClick={() => onSelectAgent?.(task.agentId)}\n className=\"text-sm text-[var(--color-accent)] hover:underline\"\n >\n {task.agentName}\n </button>\n )}\n </div>\n\n {/* Description */}\n {editing ? (\n <div>\n <h4 className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1\">Description</h4>\n <textarea\n value={editForm.description}\n onChange={e => setEditForm({ ...editForm, description: e.target.value })}\n className={`${inputClass} resize-none`}\n rows={3}\n placeholder=\"Task description...\"\n />\n </div>\n ) : task.description ? (\n <div>\n <h4 className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1\">Description</h4>\n <p className=\"text-sm text-[var(--color-text-secondary)] whitespace-pre-wrap\">{task.description}</p>\n </div>\n ) : null}\n\n {/* Metadata */}\n {editing ? (\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block\">Type</label>\n <select\n value={editForm.type}\n onChange={e => setEditForm({ ...editForm, type: e.target.value as \"once\" | \"recurring\" })}\n className={inputClass}\n >\n <option value=\"once\">One-time</option>\n <option value=\"recurring\">Recurring</option>\n </select>\n </div>\n <div>\n <label className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block\">Priority</label>\n <input\n type=\"number\"\n min={1}\n max={10}\n value={editForm.priority}\n onChange={e => setEditForm({ ...editForm, priority: Number(e.target.value) })}\n className={inputClass}\n />\n </div>\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <span className=\"text-[var(--color-text-muted)]\">Type</span>\n <p className=\"capitalize\">{task.type}</p>\n </div>\n <div>\n <span className=\"text-[var(--color-text-muted)]\">Priority</span>\n <p>{task.priority}</p>\n </div>\n <div>\n <span className=\"text-[var(--color-text-muted)]\">Source</span>\n <p className=\"capitalize\">{task.source}</p>\n </div>\n {task.recurrence && (\n <div>\n <span className=\"text-[var(--color-text-muted)]\">Recurrence</span>\n <p>{formatCron(task.recurrence)}</p>\n <p className=\"text-xs text-[var(--color-text-faint)] mt-0.5 font-mono\">{task.recurrence}</p>\n </div>\n )}\n </div>\n )}\n\n {/* Schedule (edit mode) */}\n {editing && editForm.type === \"once\" && (\n <div>\n <label className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block\">Schedule</label>\n <input\n type=\"datetime-local\"\n value={editForm.execute_at}\n onChange={e => setEditForm({ ...editForm, execute_at: e.target.value })}\n className={inputClass}\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">Leave empty for manual execution</p>\n </div>\n )}\n {editing && editForm.type === \"recurring\" && (\n <div>\n <label className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block\">Cron Schedule</label>\n <input\n type=\"text\"\n value={editForm.recurrence}\n onChange={e => setEditForm({ ...editForm, recurrence: e.target.value })}\n className={`${inputClass} font-mono`}\n placeholder=\"*/30 * * * *\"\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">e.g. */30 * * * * = every 30 min</p>\n </div>\n )}\n\n {/* Timestamps (view mode only) */}\n {!editing && (\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span className=\"text-[var(--color-text-muted)]\">Created</span>\n <span>{new Date(task.created_at).toLocaleString()}</span>\n </div>\n {task.execute_at && (\n <div className=\"flex justify-between\">\n <span className=\"text-[var(--color-text-muted)]\">Scheduled</span>\n <span className=\"text-[var(--color-accent)]\">{formatRelativeTime(task.execute_at)}</span>\n </div>\n )}\n {task.executed_at && (\n <div className=\"flex justify-between\">\n <span className=\"text-[var(--color-text-muted)]\">Started</span>\n <span>{new Date(task.executed_at).toLocaleString()}</span>\n </div>\n )}\n {task.completed_at && (\n <div className=\"flex justify-between\">\n <span className=\"text-[var(--color-text-muted)]\">Completed</span>\n <span>{new Date(task.completed_at).toLocaleString()}</span>\n </div>\n )}\n {task.next_run && (\n <div className=\"flex justify-between\">\n <span className=\"text-[var(--color-text-muted)]\">Next Run</span>\n <span className=\"text-[var(--color-accent)]\">{formatRelativeTime(task.next_run)}</span>\n </div>\n )}\n </div>\n )}\n\n {/* Error */}\n {task.status === \"failed\" && task.error && (\n <div className=\"min-w-0\">\n <h4 className=\"text-xs text-red-400 uppercase tracking-wider mb-1\">Error</h4>\n <div className=\"bg-red-500/10 border border-red-500/20 rounded p-3 overflow-x-auto\">\n <pre className=\"text-sm text-red-400 whitespace-pre-wrap break-words\">{task.error}</pre>\n </div>\n </div>\n )}\n\n {/* Result */}\n {task.status === \"completed\" && task.result && (\n <div className=\"min-w-0\">\n <h4 className=\"text-xs text-green-400 uppercase tracking-wider mb-1\">Result</h4>\n <div className=\"bg-green-500/10 border border-green-500/20 rounded p-3 overflow-x-auto\">\n <pre className=\"text-sm text-green-400 whitespace-pre-wrap break-words\">\n {typeof task.result === \"string\" ? task.result : JSON.stringify(task.result, null, 2)}\n </pre>\n </div>\n </div>\n )}\n\n {/* Trajectory */}\n {loading && !task.trajectory && (\n <div>\n <h4 className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-2\">Trajectory</h4>\n <div className=\"text-sm text-[var(--color-text-faint)]\">Loading trajectory...</div>\n </div>\n )}\n {task.trajectory && task.trajectory.length > 0 && (\n <div>\n <h4 className=\"text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-2\">\n Trajectory ({task.trajectory.length} steps)\n </h4>\n <TrajectoryView trajectory={task.trajectory} />\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport function TrajectoryView({ trajectory }: { trajectory: TaskTrajectoryStep[] }) {\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const toggleStep = (id: string) => {\n setExpanded(prev => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n };\n\n const roleStyles = {\n user: { bg: \"bg-blue-500/10\", text: \"text-blue-400\", icon: \"👤\", label: \"User\" },\n assistant: { bg: \"bg-purple-500/10\", text: \"text-purple-400\", icon: \"🤖\", label: \"Assistant\" },\n };\n\n // Render content which can be string or array of blocks\n const renderContent = (step: TaskTrajectoryStep) => {\n const content = step.content;\n\n // String content (text message)\n if (typeof content === \"string\") {\n const isLong = content.length > 200;\n const isExpanded = expanded.has(step.id);\n\n return (\n <div>\n <p className={`text-sm text-[var(--color-text)] whitespace-pre-wrap break-words ${!isExpanded && isLong ? 'line-clamp-4' : ''}`}>\n {content}\n </p>\n {isLong && (\n <button\n onClick={() => toggleStep(step.id)}\n className=\"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1\"\n >\n {isExpanded ? \"Show less\" : \"Show more...\"}\n </button>\n )}\n </div>\n );\n }\n\n // Array content (tool_use or tool_result blocks)\n return (\n <div className=\"space-y-2\">\n {content.map((block, idx) => {\n if (block.type === \"tool_use\") {\n const inputStr = JSON.stringify(block.input, null, 2);\n const isLong = inputStr.length > 150;\n const blockId = `${step.id}-${idx}`;\n const isExpanded = expanded.has(blockId);\n\n return (\n <div key={idx} className=\"bg-orange-500/10 border border-orange-500/20 rounded p-2\">\n <div className=\"flex items-center gap-2 mb-1\">\n <span className=\"text-orange-400\">🔧</span>\n <span className=\"text-xs font-medium text-orange-400\">Tool Call</span>\n <span className=\"text-xs text-[var(--color-text-secondary)]\">{block.name}</span>\n </div>\n <pre className={`text-xs text-[var(--color-text-secondary)] overflow-x-auto ${!isExpanded && isLong ? 'line-clamp-3' : ''}`}>\n {inputStr}\n </pre>\n {isLong && (\n <button\n onClick={() => toggleStep(blockId)}\n className=\"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1\"\n >\n {isExpanded ? \"Show less\" : \"Show more...\"}\n </button>\n )}\n </div>\n );\n }\n\n if (block.type === \"tool_result\") {\n const isError = block.is_error;\n const blockId = `${step.id}-${idx}`;\n const isExpanded = expanded.has(blockId);\n const isLong = block.content.length > 150;\n\n return (\n <div\n key={idx}\n className={`${isError ? 'bg-red-500/10 border-red-500/20' : 'bg-teal-500/10 border-teal-500/20'} border rounded p-2`}\n >\n <div className=\"flex items-center gap-2 mb-1\">\n <span>{isError ? \"❌\" : \"📋\"}</span>\n <span className={`text-xs font-medium ${isError ? 'text-red-400' : 'text-teal-400'}`}>\n Tool Result\n </span>\n </div>\n <pre className={`text-xs text-[var(--color-text-secondary)] overflow-x-auto whitespace-pre-wrap break-words ${!isExpanded && isLong ? 'line-clamp-3' : ''}`}>\n {block.content}\n </pre>\n {isLong && (\n <button\n onClick={() => toggleStep(blockId)}\n className=\"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] mt-1\"\n >\n {isExpanded ? \"Show less\" : \"Show more...\"}\n </button>\n )}\n </div>\n );\n }\n\n return null;\n })}\n </div>\n );\n };\n\n return (\n <div className=\"space-y-2\">\n {trajectory.map((step) => {\n const style = roleStyles[step.role] || roleStyles.assistant;\n\n return (\n <div\n key={step.id}\n className={`${style.bg} border border-[var(--color-border)] rounded overflow-hidden p-3`}\n >\n <div className=\"flex items-center gap-2 mb-2\">\n <span>{style.icon}</span>\n <span className={`text-xs font-medium ${style.text}`}>{style.label}</span>\n {step.model && (\n <span className=\"text-xs text-[var(--color-text-faint)]\">· {step.model}</span>\n )}\n <span className=\"text-xs text-[var(--color-text-faint)]\">\n · {new Date(step.created_at).toLocaleTimeString()}\n </span>\n </div>\n {renderContent(step)}\n </div>\n );\n })}\n </div>\n );\n}\n\n// --- Create Task Modal ---\n\ninterface CreateTaskModalProps {\n authFetch: (url: string, options?: RequestInit) => Promise<Response>;\n currentProjectId: string | null;\n onClose: () => void;\n onCreated: () => void;\n}\n\nfunction CreateTaskModal({ authFetch, currentProjectId, onClose, onCreated }: CreateTaskModalProps) {\n const [agents, setAgents] = useState<{ id: string; name: string }[]>([]);\n const [agentId, setAgentId] = useState(\"\");\n const [title, setTitle] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [type, setType] = useState<\"once\" | \"recurring\">(\"once\");\n const [priority, setPriority] = useState(5);\n const [executeAt, setExecuteAt] = useState(\"\");\n const [recurrence, setRecurrence] = useState(\"\");\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState(\"\");\n\n useEffect(() => {\n authFetch(\"/api/agents\").then(r => r.json()).then(data => {\n const running = (data.agents || []).filter((a: Agent) => a.status === \"running\" && a.features?.tasks);\n setAgents(running.map((a: Agent) => ({ id: a.id, name: a.name })));\n if (running.length === 1) setAgentId(running[0].id);\n }).catch(() => {});\n }, [authFetch]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!agentId || !title.trim()) return;\n setCreating(true);\n setError(\"\");\n\n const body: Record<string, unknown> = {\n title: title.trim(),\n description: description.trim() || undefined,\n type,\n priority,\n };\n if (type === \"once\" && executeAt) {\n body.execute_at = new Date(executeAt).toISOString();\n }\n if (type === \"recurring\" && recurrence.trim()) {\n body.recurrence = recurrence.trim();\n }\n\n try {\n const res = await authFetch(`/api/tasks/${agentId}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n setError(data.error || `HTTP ${res.status}`);\n return;\n }\n onCreated();\n } catch (err) {\n setError(String(err));\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4\" onClick={onClose}>\n <div className=\"bg-[var(--color-surface)] card w-full max-w-md\" onClick={e => e.stopPropagation()}>\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--color-border)]\">\n <h2 className=\"font-medium\">Create Task</h2>\n <button onClick={onClose} className=\"text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition\">\n <CloseIcon />\n </button>\n </div>\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {/* Agent */}\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Agent</label>\n {agents.length === 0 ? (\n <p className=\"text-sm text-[var(--color-text-faint)]\">No running agents with tasks enabled</p>\n ) : (\n <select\n value={agentId}\n onChange={e => setAgentId(e.target.value)}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm\"\n required\n >\n <option value=\"\">Select agent...</option>\n {agents.map(a => <option key={a.id} value={a.id}>{a.name}</option>)}\n </select>\n )}\n </div>\n\n {/* Title */}\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Title</label>\n <input\n type=\"text\"\n value={title}\n onChange={e => setTitle(e.target.value)}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm\"\n placeholder=\"e.g. Check email for new orders\"\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Description</label>\n <textarea\n value={description}\n onChange={e => setDescription(e.target.value)}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm resize-none\"\n rows={2}\n placeholder=\"Optional instructions for the agent...\"\n />\n </div>\n\n {/* Type & Priority */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Type</label>\n <select\n value={type}\n onChange={e => setType(e.target.value as \"once\" | \"recurring\")}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm\"\n >\n <option value=\"once\">One-time</option>\n <option value=\"recurring\">Recurring</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Priority</label>\n <input\n type=\"number\"\n min={1}\n max={10}\n value={priority}\n onChange={e => setPriority(Number(e.target.value))}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm\"\n />\n </div>\n </div>\n\n {/* Schedule */}\n {type === \"once\" && (\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Schedule (optional)</label>\n <input\n type=\"datetime-local\"\n value={executeAt}\n onChange={e => setExecuteAt(e.target.value)}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm\"\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">Leave empty to execute immediately</p>\n </div>\n )}\n\n {type === \"recurring\" && (\n <div>\n <label className=\"block text-sm text-[var(--color-text-muted)] mb-1\">Cron Schedule</label>\n <input\n type=\"text\"\n value={recurrence}\n onChange={e => setRecurrence(e.target.value)}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border)] rounded px-3 py-2 text-sm font-mono\"\n placeholder=\"*/30 * * * *\"\n required\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">e.g. */30 * * * * = every 30 min, 0 9 * * 1-5 = weekdays at 9am</p>\n </div>\n )}\n\n {error && (\n <p className=\"text-sm text-red-400\">{error}</p>\n )}\n\n <div className=\"flex justify-end gap-2 pt-2\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 rounded text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-border)] transition\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={creating || !agentId || !title.trim() || agents.length === 0}\n className=\"px-4 py-2 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition disabled:opacity-50\"\n >\n {creating ? \"Creating...\" : \"Create Task\"}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n\n// --- Schedule formatting helpers ---\n\nconst DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\nexport function formatCron(cron: string): string {\n try {\n const parts = cron.trim().split(/\\s+/);\n if (parts.length !== 5) return cron;\n const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;\n\n // Every N minutes: */N * * * *\n if (minute.startsWith(\"*/\") && hour === \"*\" && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n const n = parseInt(minute.slice(2));\n if (n === 1) return \"Every minute\";\n return `Every ${n} minutes`;\n }\n\n // Every hour: 0 * * * *\n if (minute !== \"*\" && !minute.includes(\"/\") && hour === \"*\" && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n return \"Every hour\";\n }\n\n // Every N hours: 0 */N * * *\n if (hour.startsWith(\"*/\") && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n const n = parseInt(hour.slice(2));\n if (n === 1) return \"Every hour\";\n return `Every ${n} hours`;\n }\n\n const formatTime = (h: string, m: string): string => {\n const hr = parseInt(h);\n const mn = parseInt(m);\n if (isNaN(hr)) return \"\";\n const ampm = hr >= 12 ? \"PM\" : \"AM\";\n const h12 = hr === 0 ? 12 : hr > 12 ? hr - 12 : hr;\n return `${h12}:${mn.toString().padStart(2, \"0\")} ${ampm}`;\n };\n\n if (hour !== \"*\" && !hour.includes(\"/\") && dayOfMonth === \"*\" && month === \"*\") {\n const timeStr = formatTime(hour, minute);\n\n if (dayOfWeek === \"*\") return `Daily at ${timeStr}`;\n\n const days = dayOfWeek.split(\",\").map(d => {\n const num = parseInt(d.trim());\n return DAY_NAMES[num] || d;\n });\n\n if (days.length === 7) return `Daily at ${timeStr}`;\n if (days.length === 5 && !days.includes(\"Sat\") && !days.includes(\"Sun\")) {\n return `Weekdays at ${timeStr}`;\n }\n if (days.length === 1) return `Weekly on ${days[0]} at ${timeStr}`;\n return `${days.join(\" & \")} at ${timeStr}`;\n }\n\n return cron;\n } catch {\n return cron;\n }\n}\n\nexport function formatRelativeTime(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const diffMs = date.getTime() - now.getTime();\n const absDiffMs = Math.abs(diffMs);\n const isFuture = diffMs > 0;\n\n const minutes = Math.floor(absDiffMs / 60000);\n const hours = Math.floor(absDiffMs / 3600000);\n const days = Math.floor(absDiffMs / 86400000);\n\n const timeStr = date.toLocaleTimeString([], { hour: \"numeric\", minute: \"2-digit\" });\n\n const isToday = date.toDateString() === now.toDateString();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n const isTomorrow = date.toDateString() === tomorrow.toDateString();\n const yesterday = new Date(now);\n yesterday.setDate(yesterday.getDate() - 1);\n const isYesterday = date.toDateString() === yesterday.toDateString();\n\n if (isToday) {\n if (minutes < 1) return isFuture ? \"now\" : \"just now\";\n if (minutes < 60) return isFuture ? `in ${minutes} min (${timeStr})` : `${minutes} min ago`;\n return isFuture ? `in ${hours}h (${timeStr})` : `${hours}h ago`;\n }\n\n if (isTomorrow) return `Tomorrow at ${timeStr}`;\n if (isYesterday) return `Yesterday at ${timeStr}`;\n\n if (days < 7) {\n const dayName = DAY_NAMES[date.getDay()];\n return `${dayName} at ${timeStr}`;\n }\n\n return date.toLocaleDateString([], { month: \"short\", day: \"numeric\" }) + ` at ${timeStr}`;\n}\n"
6
+ ],
7
+ "mappings": "mPAAA,sBAYO,CAAS,NAAS,EAAG,iBAAiC,CAC3D,IAAQ,aAAc,EAAQ,GACtB,oBAAqB,EAAY,GAClC,EAAO,GAAY,WAAiB,CAAC,CAAC,GACtC,EAAS,GAAc,WAAS,EAAI,GACpC,EAAQ,GAAa,WAAiB,KAAK,GAC3C,EAAa,GAAkB,WAAiB,KAAK,GACrD,EAAc,GAAmB,WAAsB,IAAI,GAC3D,EAAa,GAAkB,WAAS,EAAK,GAC7C,EAAiB,GAAsB,WAAS,EAAK,EACtD,EAAwB,SAAsB,IAAI,GAGhD,OAAQ,GAAe,EAAa,CAAE,SAAU,MAAO,CAAC,EAE1D,EAAa,cAAY,SAAY,CACzC,GAAI,CACF,IAAI,EAAM,qBAAqB,IAC/B,GAAI,IAAqB,KACvB,GAAO,eAAe,mBAAmB,CAAgB,IAG3D,IAAM,EAAO,MADD,MAAM,EAAU,CAAG,GACR,KAAK,EAC5B,EAAS,EAAK,OAAS,CAAC,CAAC,EACzB,MAAO,EAAG,CACV,QAAQ,MAAM,yBAA0B,CAAC,SACzC,CACA,EAAW,EAAK,IAEjB,CAAC,EAAW,EAAQ,CAAgB,CAAC,EAGxC,YAAU,IAAM,CACd,EAAW,GACV,CAAC,CAAU,CAAC,EAIf,YAAU,IAAM,CACd,GAAI,CAAC,EAAW,OAAQ,OAExB,IAAM,EAAc,EAAW,GAC/B,GAAI,CAAC,GAAe,EAAY,KAAO,EAAsB,QAAS,OAGtE,IAAM,EAAY,EAAY,KAC9B,GAAI,IAAc,gBAAkB,IAAc,gBAAkB,IAAc,eAChF,EAAsB,QAAU,EAAY,GAC5C,QAAQ,IAAI,+BAAgC,CAAS,EAErD,EAAW,GAEZ,CAAC,EAAY,CAAU,CAAC,EAG3B,IAAM,EAAa,cAAY,MAAO,IAAe,CAEnD,EAAgB,CAAI,EACpB,EAAe,EAAI,EAEnB,GAAI,CACF,IAAM,EAAM,MAAM,EAAU,cAAc,EAAK,WAAW,EAAK,IAAI,EAEnE,GADA,QAAQ,IAAI,0CAA2C,EAAI,MAAM,EAC7D,EAAI,GAAI,CACV,IAAM,EAAO,MAAM,EAAI,KAAK,EAG5B,GAFA,QAAQ,IAAI,yBAA0B,CAAI,EAC1C,QAAQ,IAAI,8BAA+B,CAAC,CAAC,EAAK,MAAM,WAAY,UAAW,EAAK,MAAM,YAAY,MAAM,EACxG,EAAK,KAEP,EAAgB,IAAK,EAAK,KAAM,QAAS,EAAK,QAAS,UAAW,EAAK,SAAU,CAAC,EAGpF,aAAQ,MAAM,oCAAqC,EAAI,OAAQ,MAAM,EAAI,KAAK,CAAC,EAEjF,MAAO,EAAG,CACV,QAAQ,MAAM,gCAAiC,CAAC,SAChD,CACA,EAAe,EAAK,IAErB,CAAC,CAAS,CAAC,EAGR,EAAe,UAAQ,IAAM,CACjC,IAAM,EAAM,IAAI,IAChB,QAAW,KAAK,EAAO,CACrB,IAAM,EAAK,EAAE,SAAY,EAAU,SAC7B,EAAO,EAAE,WAAc,EAAU,WACvC,GAAI,GAAM,GAAQ,CAAC,EAAI,IAAI,CAAE,EAC3B,EAAI,IAAI,EAAI,CAAI,EAGpB,OAAO,MAAM,KAAK,EAAI,QAAQ,CAAC,EAAE,KAAK,CAAC,EAAG,IAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC,GACvE,CAAC,CAAK,CAAC,EAGJ,EAAc,UAAQ,IAAM,CAEhC,MAAO,CAAC,GADS,IAAgB,MAAQ,EAAQ,EAAM,OAAO,MAAM,EAAE,SAAY,EAAU,YAAc,CAAW,CAClG,EAAE,KAAK,CAAC,EAAG,IAAM,CAElC,GAAI,EAAE,SAAW,WAAa,EAAE,SAAW,UAAW,MAAO,GAC7D,GAAI,EAAE,SAAW,WAAa,EAAE,SAAW,UAAW,MAAO,GAE7D,IAAM,EAAa,EAAE,SAAW,UAC1B,EAAa,EAAE,SAAW,UAChC,GAAI,GAAc,CAAC,EAAY,MAAO,GACtC,GAAI,GAAc,CAAC,EAAY,MAAO,GAEtC,GAAI,GAAc,GAAc,EAAE,SAAW,WAAa,EAAE,SAAW,UAAW,CAChF,IAAM,EAAQ,EAAE,UAAY,EAAE,YAAc,KACtC,EAAQ,EAAE,UAAY,EAAE,YAAc,KACtC,EAAM,EAAQ,IAAI,KAAK,CAAK,EAAE,QAAQ,EAAI,IAC1C,EAAM,EAAQ,IAAI,KAAK,CAAK,EAAE,QAAQ,EAAI,IAChD,OAAO,EAAM,EAGf,IAAM,EAAQ,EAAE,cAAgB,EAAE,aAAe,EAAE,WAC7C,EAAQ,EAAE,cAAgB,EAAE,aAAe,EAAE,WACnD,OAAO,IAAI,KAAK,CAAK,EAAE,QAAQ,EAAI,IAAI,KAAK,CAAK,EAAE,QAAQ,EAC5D,GACA,CAAC,EAAO,CAAW,CAAC,EAEjB,EAAuC,CAC3C,QAAS,mCACT,QAAS,+BACT,UAAW,iCACX,OAAQ,6BACR,UAAW,8BACb,EAUA,OACE,SA2IE,MA3IF,CAAK,UAAU,8BAAf,SA2IE,CAzIA,SAiHE,MAjHF,CAAK,UAAW,mCAAmC,EAAe,oCAAsC,KAAxG,SACE,SA+GE,MA/GF,CAAK,UAAU,YAAf,SA+GE,CA9GA,SA+CE,MA/CF,CAAK,UAAU,OAAf,SA+CE,CA9CA,SAcE,MAdF,CAAK,UAAU,wCAAf,SAcE,CAbA,SAKE,MALF,UAKE,CAJA,SAA8D,KAA9D,CAAI,UAAU,yCAAd,uCAA8D,EAC9D,SAEE,IAFF,CAAG,UAAU,yCAAb,oEAEE,IAJJ,qBAKE,EACF,SAME,SANF,CACE,QAAS,IAAM,EAAmB,EAAI,EACtC,UAAU,sIAFZ,SAME,CAFA,SAAyK,MAAzK,CAAK,UAAU,UAAU,KAAK,OAAO,OAAO,eAAe,QAAQ,YAAnE,SAA+E,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,kBAArE,qBAAsF,GAArK,qBAAyK,EAJ3K,qCAME,IAbJ,qBAcE,EACF,SA8BE,MA9BF,CAAK,UAAU,yCAAf,SA8BE,CA7BA,SAcE,MAdF,CAAK,UAAU,4CAAf,SA9BU,CACpB,CAAE,MAAO,MAAO,MAAO,KAAM,EAC7B,CAAE,MAAO,UAAW,MAAO,SAAU,EACrC,CAAE,MAAO,UAAW,MAAO,SAAU,EACrC,CAAE,MAAO,YAAa,MAAO,WAAY,EACzC,CAAE,MAAO,SAAU,MAAO,QAAS,CACrC,EAyB6B,IAAI,KACjB,SAUE,SAVF,CAEE,QAAS,IAAM,EAAU,EAAI,KAAK,EAClC,UAAW,4DACT,IAAW,EAAI,MACX,sCACA,4EANR,SASG,EAAI,OARA,EAAI,MADX,cAUE,CACH,GAbH,qBAcE,EACD,EAAa,OAAS,GACrB,SAWE,MAXF,CAAK,UAAU,OAAf,SACE,SAAC,EAAD,CACE,MAAO,EACP,SAAU,EACV,YAAY,aACZ,QAAO,GACP,QAAS,CACP,CAAE,MAAO,MAAO,MAAO,YAAa,EACpC,GAAG,EAAa,IAAI,EAAE,EAAI,MAAW,CAAE,MAAO,EAAI,MAAO,CAAK,EAAE,CAClE,GARF,qBASA,GAVF,qBAWE,IA5BN,qBA8BE,IA9CJ,qBA+CE,EAED,EACC,SAAoF,MAApF,CAAK,UAAU,mDAAf,kDAAoF,EAClF,EAAY,SAAW,EACzB,SAME,MANF,CAAK,UAAU,oBAAf,SAME,CALA,SAAC,EAAD,CAAW,UAAU,2DAArB,qBAA+E,EAC/E,SAA8D,IAA9D,CAAG,UAAU,iCAAb,gDAA8D,EAC9D,SAEE,IAFF,CAAG,UAAU,8CAAb,gFAEE,IALJ,qBAME,EAEF,SAgDE,MAhDF,CAAK,UAAU,YAAf,SACG,EAAY,IAAI,KACf,SA4CE,MA5CF,CAEE,QAAS,IAAM,EAAW,CAAI,EAC9B,UAAW,6EACT,GAAc,KAAO,EAAK,IAAM,GAAc,UAAY,EAAK,QAC3D,+BACA,0EANR,SA4CE,CAnCA,SAQE,MARF,CAAK,UAAU,wCAAf,SAQE,CAPA,SAGE,MAHF,CAAK,UAAU,SAAf,SAGE,CAFA,SAA0C,KAA1C,CAAI,UAAU,cAAd,SAA6B,EAAK,OAAlC,qBAA0C,EAC1C,SAAwE,IAAxE,CAAG,UAAU,yCAAb,SAAuD,EAAK,WAA5D,qBAAwE,IAF1E,qBAGE,EACF,SAEE,OAFF,CAAM,UAAW,yCAAyC,EAAa,EAAK,SAAW,EAAa,UAApG,SACG,EAAK,QADR,qBAEE,IAPJ,qBAQE,EAED,EAAK,aACJ,SAEE,IAFF,CAAG,UAAU,+DAAb,SACG,EAAK,aADR,qBAEE,EAGJ,SAkBE,MAlBF,CAAK,UAAU,qFAAf,SAkBE,CAjBA,SAQE,OARF,CAAM,UAAU,0BAAhB,SAQE,CAPC,EAAK,OAAS,YACX,SAAC,EAAD,CAAe,UAAU,eAAzB,qBAAuC,EACvC,EAAK,WACH,SAAC,EAAD,CAAe,UAAU,eAAzB,qBAAuC,EACvC,SAAC,EAAD,CAAc,UAAU,eAAxB,qBAAsC,EAE3C,EAAK,OAAS,aAAe,EAAK,WAAa,EAAW,EAAK,UAAU,EAAI,EAAK,OAPrF,qBAQE,EACF,SAAiC,OAAjC,UAAiC,CAAjC,aAAiB,EAAK,WAAtB,qBAAiC,EAChC,EAAK,UACJ,SAAkF,OAAlF,CAAM,UAAU,6BAAhB,SAA8C,EAAmB,EAAK,QAAQ,GAA9E,qBAAkF,EAEnF,CAAC,EAAK,UAAY,EAAK,YACtB,SAAoF,OAApF,CAAM,UAAU,6BAAhB,SAA8C,EAAmB,EAAK,UAAU,GAAhF,qBAAoF,EAEtF,SAAiE,OAAjE,UAAiE,CAAjE,YAAgB,IAAI,KAAK,EAAK,UAAU,EAAE,mBAAmB,IAA7D,qBAAiE,IAjBnE,qBAkBE,IA1CG,GAAG,EAAK,WAAW,EAAK,KAD/B,cA4CE,CACH,GA/CH,qBAgDE,IA7GN,qBA+GE,GAhHJ,qBAiHE,EAGD,GACC,SAAC,GAAD,CACE,KAAM,EACN,aAAc,EACd,QAAS,IAAM,EAAgB,IAAI,EACnC,cAAe,EACf,QAAS,EACT,UAAW,EACX,UAAW,IAAM,CAAE,EAAW,EAAG,EAAgB,IAAI,IAPvD,qBAQA,EAID,GACC,SAAC,GAAD,CACE,UAAW,EACX,iBAAkB,EAClB,QAAS,IAAM,EAAmB,EAAK,EACvC,UAAW,IAAM,CAAE,EAAW,EAAG,EAAmB,EAAK,IAJ3D,qBAKA,IAzIJ,qBA2IE,EAcC,SAAS,EAAe,EAAG,OAAM,eAAc,UAAS,gBAAe,UAAS,YAAW,aAAmC,CACnI,IAAO,EAAW,GAAgB,WAAS,EAAK,GACzC,EAAU,GAAe,WAAS,EAAK,GACvC,EAAS,GAAc,WAAS,EAAK,GACrC,EAAQ,GAAa,WAAS,EAAK,GACnC,EAAU,GAAe,WAAS,CACvC,MAAO,EAAK,MACZ,YAAa,EAAK,aAAe,GACjC,KAAM,EAAK,KACX,SAAU,EAAK,SACf,WAAY,EAAK,WAAa,IAAI,KAAK,EAAK,UAAU,EAAE,YAAY,EAAE,MAAM,EAAG,EAAE,EAAI,GACrF,WAAY,EAAK,YAAc,EACjC,CAAC,GACO,UAAS,iBAAkB,EAAW,EAG9C,YAAU,IAAM,CACd,EAAY,CACV,MAAO,EAAK,MACZ,YAAa,EAAK,aAAe,GACjC,KAAM,EAAK,KACX,SAAU,EAAK,SACf,WAAY,EAAK,WAAa,IAAI,KAAK,EAAK,UAAU,EAAE,YAAY,EAAE,MAAM,EAAG,EAAE,EAAI,GACrF,WAAY,EAAK,YAAc,EACjC,CAAC,EACD,EAAW,EAAK,GACf,CAAC,EAAK,GAAI,EAAK,OAAO,CAAC,EAE1B,IAAM,EAAa,SAAY,CAC7B,GAAI,CAAC,GAAa,EAAQ,OAC1B,EAAU,EAAI,EACd,GAAI,CACF,IAAM,EAAgC,CACpC,MAAO,EAAS,MAAM,KAAK,EAC3B,YAAa,EAAS,YAAY,KAAK,GAAK,OAC5C,KAAM,EAAS,KACf,SAAU,EAAS,QACrB,EACA,GAAI,EAAS,OAAS,QAAU,EAAS,WACvC,EAAK,WAAa,IAAI,KAAK,EAAS,UAAU,EAAE,YAAY,EAE9D,GAAI,EAAS,OAAS,aAAe,EAAS,WAAW,KAAK,EAC5D,EAAK,WAAa,EAAS,WAAW,KAAK,EAO7C,IALY,MAAM,EAAU,cAAc,EAAK,WAAW,EAAK,KAAM,CACnE,OAAQ,MACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAI,CAC3B,CAAC,GACO,GACN,EAAW,EAAK,EAChB,IAAY,EAEd,MAAO,EAAG,CACV,QAAQ,MAAM,yBAA0B,CAAC,SACzC,CACA,EAAU,EAAK,IAIb,EAAgB,SAAY,CAChC,GAAI,CAAC,GAAa,EAAW,OAC7B,EAAa,EAAI,EACjB,GAAI,CACF,MAAM,EAAU,cAAc,EAAK,WAAW,EAAK,aAAc,CAAE,OAAQ,MAAO,CAAC,EACnF,IAAY,EACZ,MAAO,EAAG,CACV,QAAQ,MAAM,0BAA2B,CAAC,SAC1C,CACA,EAAa,EAAK,IAIhB,EAAe,SAAY,CAC/B,GAAI,CAAC,GAAa,EAAU,OAM5B,GAAI,CALO,MAAM,EAAQ,oCAAoC,EAAK,UAAW,CAC3E,MAAO,cACP,YAAa,SACb,eAAgB,QAClB,CAAC,EACQ,OACT,EAAY,EAAI,EAChB,GAAI,CACF,MAAM,EAAU,cAAc,EAAK,WAAW,EAAK,KAAM,CAAE,OAAQ,QAAS,CAAC,EAC7E,IAAY,EACZ,MAAO,EAAG,CACV,QAAQ,MAAM,yBAA0B,CAAC,SACzC,CACA,EAAY,EAAK,IAIf,EAAa,mLAEnB,OACE,SA8QE,MA9QF,CAAK,UAAU,oHAAf,SA8QE,CA7QC,EAED,SAiEE,MAjEF,CAAK,UAAU,8EAAf,SAiEE,CAhEA,SAAoF,KAApF,CAAI,UAAU,4BAAd,SAA2C,EAAU,YAAc,gBAAnE,qBAAoF,EACpF,SA8DE,MA9DF,CAAK,UAAU,0BAAf,SA8DE,CA7DC,GAAa,CAAC,IAAY,EAAK,SAAW,WAAa,EAAK,SAAW,aAAe,EAAK,SAAW,WACrG,SAME,SANF,CACE,QAAS,IAAM,EAAW,EAAI,EAC9B,MAAM,YACN,UAAU,6EAHZ,SAKE,SAAiR,MAAjR,CAAK,UAAU,UAAU,KAAK,OAAO,OAAO,eAAe,QAAQ,YAAnE,SAA+E,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,0HAArE,qBAA8L,GAA7Q,qBAAiR,GALnR,qBAME,EAEH,GAAa,CAAC,IAAY,EAAK,SAAW,WAAa,EAAK,SAAW,cACtE,SAOE,SAPF,CACE,QAAS,EACT,SAAU,EACV,MAAM,cACN,UAAU,6EAJZ,SAME,SAAuW,MAAvW,CAAK,UAAU,UAAU,KAAK,OAAO,OAAO,eAAe,QAAQ,YAAnE,SAAuW,CAAxR,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,oGAArE,qBAAwK,EAAE,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,sCAArE,qBAA0G,IAAnW,qBAAuW,GANzW,qBAOE,EAEH,GAAa,CAAC,GACb,SAOE,SAPF,CACE,QAAS,EACT,SAAU,EACV,MAAM,cACN,UAAU,iEAJZ,SAME,SAAuR,MAAvR,CAAK,UAAU,UAAU,KAAK,OAAO,OAAO,eAAe,QAAQ,YAAnE,SAA+E,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,EAAG,EAAE,gIAArE,qBAAoM,GAAnR,qBAAuR,GANzR,qBAOE,EAEH,GACC,8BAwBE,CAvBA,SAeE,SAfF,CACE,QAAS,IAAM,CACb,EAAW,EAAK,EAChB,EAAY,CACV,MAAO,EAAK,MACZ,YAAa,EAAK,aAAe,GACjC,KAAM,EAAK,KACX,SAAU,EAAK,SACf,WAAY,EAAK,WAAa,IAAI,KAAK,EAAK,UAAU,EAAE,YAAY,EAAE,MAAM,EAAG,EAAE,EAAI,GACrF,WAAY,EAAK,YAAc,EACjC,CAAC,GAEH,UAAU,mFAZZ,wCAeE,EACF,SAME,SANF,CACE,QAAS,EACT,SAAU,GAAU,CAAC,EAAS,MAAM,KAAK,EACzC,UAAU,gHAHZ,SAKG,EAAS,YAAc,QAL1B,qBAME,IAvBJ,qBAwBE,EAEH,CAAC,GACA,SAEE,SAFF,CAAQ,QAAS,EAAS,UAAU,2EAApC,SACE,SAAC,EAAD,wBAAW,GADb,qBAEE,IA5DN,qBA8DE,IAhEJ,qBAiEE,EAGF,SAsME,MAtMF,CAAK,UAAU,qCAAf,SAsME,CApMA,SA2BE,MA3BF,UA2BE,CA1BA,SAiBE,MAjBF,CAAK,UAAU,8CAAf,SAiBE,CAhBC,EACC,SAAC,QAAD,CACE,KAAK,OACL,MAAO,EAAS,MAChB,SAAU,KAAK,EAAY,IAAK,EAAU,MAAO,EAAE,OAAO,KAAM,CAAC,EACjE,UAAW,GAAG,wBACd,YAAY,cALd,qBAMA,EAEA,SAAkD,KAAlD,CAAI,UAAU,sBAAd,SAAqC,EAAK,OAA1C,qBAAkD,EAEnD,CAAC,GACA,SAEE,OAFF,CAAM,UAAW,uDAAuD,EAAa,EAAK,UAA1F,SACG,EAAK,QADR,qBAEE,IAfN,qBAiBE,EACD,CAAC,GACA,SAKE,SALF,CACE,QAAS,IAAM,IAAgB,EAAK,OAAO,EAC3C,UAAU,qDAFZ,SAIG,EAAK,WAJR,qBAKE,IAzBN,qBA2BE,EAGD,EACC,SASE,MATF,UASE,CARA,SAAkG,KAAlG,CAAI,UAAU,uEAAd,6CAAkG,EAClG,SAAC,WAAD,CACE,MAAO,EAAS,YAChB,SAAU,KAAK,EAAY,IAAK,EAAU,YAAa,EAAE,OAAO,KAAM,CAAC,EACvE,UAAW,GAAG,gBACd,KAAM,EACN,YAAY,uBALd,qBAMA,IARF,qBASE,EACA,EAAK,YACP,SAGE,MAHF,UAGE,CAFA,SAAkG,KAAlG,CAAI,UAAU,uEAAd,6CAAkG,EAClG,SAAkG,IAAlG,CAAG,UAAU,iEAAb,SAA+E,EAAK,aAApF,qBAAkG,IAFpG,qBAGE,EACA,KAGH,EACC,SAuBE,MAvBF,CAAK,UAAU,yBAAf,SAuBE,CAtBA,SAUE,MAVF,UAUE,CATA,SAAoG,QAApG,CAAO,UAAU,6EAAjB,sCAAoG,EACpG,SAOE,SAPF,CACE,MAAO,EAAS,KAChB,SAAU,KAAK,EAAY,IAAK,EAAU,KAAM,EAAE,OAAO,KAA8B,CAAC,EACxF,UAAW,EAHb,SAOE,CAFA,SAA+B,SAA/B,CAAQ,MAAM,OAAd,0CAA+B,EAC/B,SAAqC,SAArC,CAAQ,MAAM,YAAd,2CAAqC,IANvC,qBAOE,IATJ,qBAUE,EACF,SAUE,MAVF,UAUE,CATA,SAAwG,QAAxG,CAAO,UAAU,6EAAjB,0CAAwG,EACxG,SAAC,QAAD,CACE,KAAK,SACL,IAAK,EACL,IAAK,GACL,MAAO,EAAS,SAChB,SAAU,KAAK,EAAY,IAAK,EAAU,SAAU,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,EAC5E,UAAW,GANb,qBAOA,IATF,qBAUE,IAtBJ,qBAuBE,EAEF,SAoBE,MApBF,CAAK,UAAU,iCAAf,SAoBE,CAnBA,SAGE,MAHF,UAGE,CAFA,SAAuD,OAAvD,CAAM,UAAU,iCAAhB,sCAAuD,EACvD,SAAuC,IAAvC,CAAG,UAAU,aAAb,SAA2B,EAAK,MAAhC,qBAAuC,IAFzC,qBAGE,EACF,SAGE,MAHF,UAGE,CAFA,SAA2D,OAA3D,CAAM,UAAU,iCAAhB,0CAA2D,EAC3D,SAAoB,IAApB,UAAI,EAAK,UAAT,qBAAoB,IAFtB,qBAGE,EACF,SAGE,MAHF,UAGE,CAFA,SAAyD,OAAzD,CAAM,UAAU,iCAAhB,wCAAyD,EACzD,SAAyC,IAAzC,CAAG,UAAU,aAAb,SAA2B,EAAK,QAAhC,qBAAyC,IAF3C,qBAGE,EACD,EAAK,YACJ,SAIE,MAJF,UAIE,CAHA,SAA6D,OAA7D,CAAM,UAAU,iCAAhB,4CAA6D,EAC7D,SAAkC,IAAlC,UAAI,EAAW,EAAK,UAAU,GAA9B,qBAAkC,EAClC,SAA0F,IAA1F,CAAG,UAAU,0DAAb,SAAwE,EAAK,YAA7E,qBAA0F,IAH5F,qBAIE,IAlBN,qBAoBE,EAIH,GAAW,EAAS,OAAS,QAC5B,SASE,MATF,UASE,CARA,SAAwG,QAAxG,CAAO,UAAU,6EAAjB,0CAAwG,EACxG,SAAC,QAAD,CACE,KAAK,iBACL,MAAO,EAAS,WAChB,SAAU,KAAK,EAAY,IAAK,EAAU,WAAY,EAAE,OAAO,KAAM,CAAC,EACtE,UAAW,GAJb,qBAKA,EACA,SAA6F,IAA7F,CAAG,UAAU,8CAAb,kEAA6F,IAR/F,qBASE,EAEH,GAAW,EAAS,OAAS,aAC5B,SAUE,MAVF,UAUE,CATA,SAA6G,QAA7G,CAAO,UAAU,6EAAjB,+CAA6G,EAC7G,SAAC,QAAD,CACE,KAAK,OACL,MAAO,EAAS,WAChB,SAAU,KAAK,EAAY,IAAK,EAAU,WAAY,EAAE,OAAO,KAAM,CAAC,EACtE,UAAW,GAAG,cACd,YAAY,gBALd,qBAMA,EACA,SAA6F,IAA7F,CAAG,UAAU,8CAAb,kEAA6F,IAT/F,qBAUE,EAIH,CAAC,GACF,SA6BE,MA7BF,CAAK,UAAU,oBAAf,SA6BE,CA5BA,SAGE,MAHF,CAAK,UAAU,uBAAf,SAGE,CAFA,SAA0D,OAA1D,CAAM,UAAU,iCAAhB,yCAA0D,EAC1D,SAAoD,OAApD,UAAO,IAAI,KAAK,EAAK,UAAU,EAAE,eAAe,GAAhD,qBAAoD,IAFtD,qBAGE,EACD,EAAK,YACJ,SAGE,MAHF,CAAK,UAAU,uBAAf,SAGE,CAFA,SAA4D,OAA5D,CAAM,UAAU,iCAAhB,2CAA4D,EAC5D,SAAoF,OAApF,CAAM,UAAU,6BAAhB,SAA8C,EAAmB,EAAK,UAAU,GAAhF,qBAAoF,IAFtF,qBAGE,EAEH,EAAK,aACJ,SAGE,MAHF,CAAK,UAAU,uBAAf,SAGE,CAFA,SAA0D,OAA1D,CAAM,UAAU,iCAAhB,yCAA0D,EAC1D,SAAqD,OAArD,UAAO,IAAI,KAAK,EAAK,WAAW,EAAE,eAAe,GAAjD,qBAAqD,IAFvD,qBAGE,EAEH,EAAK,cACJ,SAGE,MAHF,CAAK,UAAU,uBAAf,SAGE,CAFA,SAA4D,OAA5D,CAAM,UAAU,iCAAhB,2CAA4D,EAC5D,SAAsD,OAAtD,UAAO,IAAI,KAAK,EAAK,YAAY,EAAE,eAAe,GAAlD,qBAAsD,IAFxD,qBAGE,EAEH,EAAK,UACJ,SAGE,MAHF,CAAK,UAAU,uBAAf,SAGE,CAFA,SAA2D,OAA3D,CAAM,UAAU,iCAAhB,0CAA2D,EAC3D,SAAkF,OAAlF,CAAM,UAAU,6BAAhB,SAA8C,EAAmB,EAAK,QAAQ,GAA9E,qBAAkF,IAFpF,qBAGE,IA3BN,qBA6BE,EAID,EAAK,SAAW,UAAY,EAAK,OAChC,SAKE,MALF,CAAK,UAAU,UAAf,SAKE,CAJA,SAA0E,KAA1E,CAAI,UAAU,qDAAd,uCAA0E,EAC1E,SAEE,MAFF,CAAK,UAAU,qEAAf,SACE,SAAoF,MAApF,CAAK,UAAU,uDAAf,SAAuE,EAAK,OAA5E,qBAAoF,GADtF,qBAEE,IAJJ,qBAKE,EAIH,EAAK,SAAW,aAAe,EAAK,QACnC,SAOE,MAPF,CAAK,UAAU,UAAf,SAOE,CANA,SAA6E,KAA7E,CAAI,UAAU,uDAAd,wCAA6E,EAC7E,SAIE,MAJF,CAAK,UAAU,yEAAf,SACE,SAEE,MAFF,CAAK,UAAU,yDAAf,SACG,OAAO,EAAK,SAAW,SAAW,EAAK,OAAS,KAAK,UAAU,EAAK,OAAQ,KAAM,CAAC,GADtF,qBAEE,GAHJ,qBAIE,IANJ,qBAOE,EAIH,GAAW,CAAC,EAAK,YAChB,SAGE,MAHF,UAGE,CAFA,SAAiG,KAAjG,CAAI,UAAU,uEAAd,4CAAiG,EACjG,SAA+E,MAA/E,CAAK,UAAU,yCAAf,uDAA+E,IAFjF,qBAGE,EAEH,EAAK,YAAc,EAAK,WAAW,OAAS,GAC3C,SAKE,MALF,UAKE,CAJA,SAEE,KAFF,CAAI,UAAU,uEAAd,SAEE,CAFF,eACe,EAAK,WAAW,OAD/B,iCAEE,EACF,SAAC,GAAD,CAAgB,WAAY,EAAK,YAAjC,qBAA6C,IAJ/C,qBAKE,IApMN,qBAsME,IA7QJ,qBA8QE,EAIC,SAAS,EAAc,EAAG,cAAoD,CACnF,IAAO,EAAU,GAAe,WAAsB,IAAI,GAAK,EAEzD,EAAa,CAAC,IAAe,CACjC,EAAY,KAAQ,CAClB,IAAM,EAAO,IAAI,IAAI,CAAI,EACzB,GAAI,EAAK,IAAI,CAAE,EACb,EAAK,OAAO,CAAE,EAEd,OAAK,IAAI,CAAE,EAEb,OAAO,EACR,GAGG,EAAa,CACjB,KAAM,CAAE,GAAI,iBAAkB,KAAM,gBAAiB,KAAM,eAAK,MAAO,MAAO,EAC9E,UAAW,CAAE,GAAI,mBAAoB,KAAM,kBAAmB,KAAM,eAAK,MAAO,WAAY,CAC9F,EAGM,EAAgB,CAAC,IAA6B,CAClD,IAAM,EAAU,EAAK,QAGrB,GAAI,OAAO,IAAY,SAAU,CAC/B,IAAM,EAAS,EAAQ,OAAS,IAC1B,EAAa,EAAS,IAAI,EAAK,EAAE,EAEvC,OACE,SAYE,MAZF,UAYE,CAXA,SAEE,IAFF,CAAG,UAAW,oEAAoE,CAAC,GAAc,EAAS,eAAiB,KAA3H,SACG,GADH,qBAEE,EACD,GACC,SAKE,SALF,CACE,QAAS,IAAM,EAAW,EAAK,EAAE,EACjC,UAAU,uFAFZ,SAIG,EAAa,YAAc,gBAJ9B,qBAKE,IAVN,qBAYE,EAKN,OACE,SAgEE,MAhEF,CAAK,UAAU,YAAf,SACG,EAAQ,IAAI,CAAC,EAAO,IAAQ,CAC3B,GAAI,EAAM,OAAS,WAAY,CAC7B,IAAM,EAAW,KAAK,UAAU,EAAM,MAAO,KAAM,CAAC,EAC9C,EAAS,EAAS,OAAS,IAC3B,EAAU,GAAG,EAAK,MAAM,IACxB,EAAa,EAAS,IAAI,CAAO,EAEvC,OACE,SAiBE,MAjBF,CAAe,UAAU,2DAAzB,SAiBE,CAhBA,SAIE,MAJF,CAAK,UAAU,+BAAf,SAIE,CAHA,SAAqC,OAArC,CAAM,UAAU,kBAAhB,8CAAqC,EACrC,SAAiE,OAAjE,CAAM,UAAU,sCAAhB,2CAAiE,EACjE,SAA2E,OAA3E,CAAM,UAAU,6CAAhB,SAA8D,EAAM,MAApE,qBAA2E,IAH7E,qBAIE,EACF,SAEE,MAFF,CAAK,UAAW,8DAA8D,CAAC,GAAc,EAAS,eAAiB,KAAvH,SACG,GADH,qBAEE,EACD,GACC,SAKE,SALF,CACE,QAAS,IAAM,EAAW,CAAO,EACjC,UAAU,uFAFZ,SAIG,EAAa,YAAc,gBAJ9B,qBAKE,IAfI,EAAV,cAiBE,EAIN,GAAI,EAAM,OAAS,cAAe,CAChC,IAAM,EAAU,EAAM,SAChB,EAAU,GAAG,EAAK,MAAM,IACxB,EAAa,EAAS,IAAI,CAAO,EACjC,EAAS,EAAM,QAAQ,OAAS,IAEtC,OACE,SAqBE,MArBF,CAEE,UAAW,GAAG,EAAU,kCAAoC,yDAF9D,SAqBE,CAjBA,SAKE,MALF,CAAK,UAAU,+BAAf,SAKE,CAJA,SAA6B,OAA7B,UAAO,EAAU,IAAK,gBAAtB,qBAA6B,EAC7B,SAEE,OAFF,CAAM,UAAW,uBAAuB,EAAU,eAAiB,kBAAnE,6CAEE,IAJJ,qBAKE,EACF,SAEE,MAFF,CAAK,UAAW,8FAA8F,CAAC,GAAc,EAAS,eAAiB,KAAvJ,SACG,EAAM,SADT,qBAEE,EACD,GACC,SAKE,SALF,CACE,QAAS,IAAM,EAAW,CAAO,EACjC,UAAU,uFAFZ,SAIG,EAAa,YAAc,gBAJ9B,qBAKE,IAlBC,EADP,cAqBE,EAIN,OAAO,KACR,GA/DH,qBAgEE,GAIN,OACE,SAuBE,MAvBF,CAAK,UAAU,YAAf,SACG,EAAW,IAAI,CAAC,IAAS,CACxB,IAAM,EAAQ,EAAW,EAAK,OAAS,EAAW,UAElD,OACE,SAeE,MAfF,CAEE,UAAW,GAAG,EAAM,qEAFtB,SAeE,CAXA,SASE,MATF,CAAK,UAAU,+BAAf,SASE,CARA,SAAoB,OAApB,UAAO,EAAM,MAAb,qBAAoB,EACpB,SAAqE,OAArE,CAAM,UAAW,uBAAuB,EAAM,OAA9C,SAAuD,EAAM,OAA7D,qBAAqE,EACpE,EAAK,OACJ,SAAwE,OAAxE,CAAM,UAAU,yCAAhB,SAAwE,CAAxE,KAA2D,EAAK,QAAhE,qBAAwE,EAE1E,SAEE,OAFF,CAAM,UAAU,yCAAhB,SAEE,CAFF,KACI,IAAI,KAAK,EAAK,UAAU,EAAE,mBAAmB,IADjD,qBAEE,IARJ,qBASE,EACD,EAAc,CAAI,IAbd,EAAK,GADZ,cAeE,EAEL,GAtBH,qBAuBE,EAaN,SAAS,EAAe,EAAG,YAAW,mBAAkB,UAAS,aAAmC,CAClG,IAAO,EAAQ,GAAa,WAAyC,CAAC,CAAC,GAChE,EAAS,GAAc,WAAS,EAAE,GAClC,EAAO,GAAY,WAAS,EAAE,GAC9B,EAAa,GAAkB,WAAS,EAAE,GAC1C,EAAM,GAAW,WAA+B,MAAM,GACtD,EAAU,GAAe,WAAS,CAAC,GACnC,EAAW,GAAgB,WAAS,EAAE,GACtC,EAAY,GAAiB,WAAS,EAAE,GACxC,EAAU,GAAe,WAAS,EAAK,GACvC,EAAO,GAAY,WAAS,EAAE,EAgDrC,OA9CA,YAAU,IAAM,CACd,EAAU,aAAa,EAAE,KAAK,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,KAAQ,CACxD,IAAM,GAAW,EAAK,QAAU,CAAC,GAAG,OAAO,CAAC,IAAa,EAAE,SAAW,WAAa,EAAE,UAAU,KAAK,EAEpG,GADA,EAAU,EAAQ,IAAI,CAAC,KAAc,CAAE,GAAI,EAAE,GAAI,KAAM,EAAE,IAAK,EAAE,CAAC,EAC7D,EAAQ,SAAW,EAAG,EAAW,EAAQ,GAAG,EAAE,EACnD,EAAE,MAAM,IAAM,EAAE,GAChB,CAAC,CAAS,CAAC,EAyCZ,SAiIE,MAjIF,CAAK,UAAU,sEAAsE,QAAS,EAA9F,SACE,SA+HE,MA/HF,CAAK,UAAU,iDAAiD,QAAS,KAAK,EAAE,gBAAgB,EAAhG,SA+HE,CA9HA,SAKE,MALF,CAAK,UAAU,8EAAf,SAKE,CAJA,SAAyC,KAAzC,CAAI,UAAU,cAAd,6CAAyC,EACzC,SAEE,SAFF,CAAQ,QAAS,EAAS,UAAU,2EAApC,SACE,SAAC,EAAD,wBAAW,GADb,qBAEE,IAJJ,qBAKE,EACF,SAuHE,OAvHF,CAAM,SA/CS,MAAO,IAAuB,CAEjD,GADA,EAAE,eAAe,EACb,CAAC,GAAW,CAAC,EAAM,KAAK,EAAG,OAC/B,EAAY,EAAI,EAChB,EAAS,EAAE,EAEX,IAAM,EAAgC,CACpC,MAAO,EAAM,KAAK,EAClB,YAAa,EAAY,KAAK,GAAK,OACnC,OACA,UACF,EACA,GAAI,IAAS,QAAU,EACrB,EAAK,WAAa,IAAI,KAAK,CAAS,EAAE,YAAY,EAEpD,GAAI,IAAS,aAAe,EAAW,KAAK,EAC1C,EAAK,WAAa,EAAW,KAAK,EAGpC,GAAI,CACF,IAAM,EAAM,MAAM,EAAU,cAAc,IAAW,CACnD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAI,CAC3B,CAAC,EACD,GAAI,CAAC,EAAI,GAAI,CACX,IAAM,EAAO,MAAM,EAAI,KAAK,EAAE,MAAM,KAAO,CAAC,EAAE,EAC9C,EAAS,EAAK,OAAS,QAAQ,EAAI,QAAQ,EAC3C,OAEF,EAAU,EACV,MAAO,EAAK,CACZ,EAAS,OAAO,CAAG,CAAC,SACpB,CACA,EAAY,EAAK,IAae,UAAU,gBAAxC,SAuHE,CArHA,SAeE,MAfF,UAeE,CAdA,SAA4E,QAA5E,CAAO,UAAU,oDAAjB,uCAA4E,EAC3E,EAAO,SAAW,EACjB,SAA4F,IAA5F,CAAG,UAAU,yCAAb,sEAA4F,EAE5F,SAQE,SARF,CACE,MAAO,EACP,SAAU,KAAK,EAAW,EAAE,OAAO,KAAK,EACxC,UAAU,4FACV,SAAQ,GAJV,SAQE,CAFA,SAAkC,SAAlC,CAAQ,MAAM,GAAd,iDAAkC,EACjC,EAAO,IAAI,KAAK,SAA0C,SAA1C,CAAmB,MAAO,EAAE,GAA5B,SAAiC,EAAE,MAAtB,EAAE,GAAf,cAA0C,CAAO,IAPpE,qBAQE,IAbN,qBAeE,EAGF,SAUE,MAVF,UAUE,CATA,SAA4E,QAA5E,CAAO,UAAU,oDAAjB,uCAA4E,EAC5E,SAAC,QAAD,CACE,KAAK,OACL,MAAO,EACP,SAAU,KAAK,EAAS,EAAE,OAAO,KAAK,EACtC,UAAU,4FACV,YAAY,kCACZ,SAAQ,IANV,qBAOA,IATF,qBAUE,EAGF,SASE,MATF,UASE,CARA,SAAkF,QAAlF,CAAO,UAAU,oDAAjB,6CAAkF,EAClF,SAAC,WAAD,CACE,MAAO,EACP,SAAU,KAAK,EAAe,EAAE,OAAO,KAAK,EAC5C,UAAU,wGACV,KAAM,EACN,YAAY,0CALd,qBAMA,IARF,qBASE,EAGF,SAuBE,MAvBF,CAAK,UAAU,yBAAf,SAuBE,CAtBA,SAUE,MAVF,UAUE,CATA,SAA2E,QAA3E,CAAO,UAAU,oDAAjB,sCAA2E,EAC3E,SAOE,SAPF,CACE,MAAO,EACP,SAAU,KAAK,EAAQ,EAAE,OAAO,KAA6B,EAC7D,UAAU,4FAHZ,SAOE,CAFA,SAA+B,SAA/B,CAAQ,MAAM,OAAd,0CAA+B,EAC/B,SAAqC,SAArC,CAAQ,MAAM,YAAd,2CAAqC,IANvC,qBAOE,IATJ,qBAUE,EACF,SAUE,MAVF,UAUE,CATA,SAA+E,QAA/E,CAAO,UAAU,oDAAjB,0CAA+E,EAC/E,SAAC,QAAD,CACE,KAAK,SACL,IAAK,EACL,IAAK,GACL,MAAO,EACP,SAAU,KAAK,EAAY,OAAO,EAAE,OAAO,KAAK,CAAC,EACjD,UAAU,6FANZ,qBAOA,IATF,qBAUE,IAtBJ,qBAuBE,EAGD,IAAS,QACR,SASE,MATF,UASE,CARA,SAA0F,QAA1F,CAAO,UAAU,oDAAjB,qDAA0F,EAC1F,SAAC,QAAD,CACE,KAAK,iBACL,MAAO,EACP,SAAU,KAAK,EAAa,EAAE,OAAO,KAAK,EAC1C,UAAU,6FAJZ,qBAKA,EACA,SAA+F,IAA/F,CAAG,UAAU,8CAAb,oEAA+F,IARjG,qBASE,EAGH,IAAS,aACR,SAWE,MAXF,UAWE,CAVA,SAAoF,QAApF,CAAO,UAAU,oDAAjB,+CAAoF,EACpF,SAAC,QAAD,CACE,KAAK,OACL,MAAO,EACP,SAAU,KAAK,EAAc,EAAE,OAAO,KAAK,EAC3C,UAAU,sGACV,YAAY,eACZ,SAAQ,IANV,qBAOA,EACA,SAA4H,IAA5H,CAAG,UAAU,8CAAb,iGAA4H,IAV9H,qBAWE,EAGH,GACC,SAA6C,IAA7C,CAAG,UAAU,uBAAb,SAAqC,GAArC,qBAA6C,EAG/C,SAeE,MAfF,CAAK,UAAU,8BAAf,SAeE,CAdA,SAME,SANF,CACE,KAAK,SACL,QAAS,EACT,UAAU,uGAHZ,wCAME,EACF,SAME,SANF,CACE,KAAK,SACL,SAAU,GAAY,CAAC,GAAW,CAAC,EAAM,KAAK,GAAK,EAAO,SAAW,EACrE,UAAU,gHAHZ,SAKG,EAAW,cAAgB,eAL9B,qBAME,IAdJ,qBAeE,IAtHJ,qBAuHE,IA9HJ,qBA+HE,GAhIJ,qBAiIE,EAMN,IAAM,EAAY,CAAC,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,KAAK,EAE3D,SAAS,CAAU,CAAC,EAAsB,CAC/C,GAAI,CACF,IAAM,EAAQ,EAAK,KAAK,EAAE,MAAM,KAAK,EACrC,GAAI,EAAM,SAAW,EAAG,OAAO,EAC/B,IAAO,EAAQ,EAAM,EAAY,EAAO,GAAa,EAGrD,GAAI,EAAO,WAAW,IAAI,GAAK,IAAS,KAAO,IAAe,KAAO,IAAU,KAAO,IAAc,IAAK,CACvG,IAAM,EAAI,SAAS,EAAO,MAAM,CAAC,CAAC,EAClC,GAAI,IAAM,EAAG,MAAO,eACpB,MAAO,SAAS,YAIlB,GAAI,IAAW,KAAO,CAAC,EAAO,SAAS,GAAG,GAAK,IAAS,KAAO,IAAe,KAAO,IAAU,KAAO,IAAc,IAClH,MAAO,aAIT,GAAI,EAAK,WAAW,IAAI,GAAK,IAAe,KAAO,IAAU,KAAO,IAAc,IAAK,CACrF,IAAM,EAAI,SAAS,EAAK,MAAM,CAAC,CAAC,EAChC,GAAI,IAAM,EAAG,MAAO,aACpB,MAAO,SAAS,UAGlB,IAAM,EAAa,CAAC,EAAW,IAAsB,CACnD,IAAM,EAAK,SAAS,CAAC,EACf,EAAK,SAAS,CAAC,EACrB,GAAI,MAAM,CAAE,EAAG,MAAO,GACtB,IAAM,EAAO,GAAM,GAAK,KAAO,KAE/B,MAAO,GADK,IAAO,EAAI,GAAK,EAAK,GAAK,EAAK,GAAK,KAC/B,EAAG,SAAS,EAAE,SAAS,EAAG,GAAG,KAAK,KAGrD,GAAI,IAAS,KAAO,CAAC,EAAK,SAAS,GAAG,GAAK,IAAe,KAAO,IAAU,IAAK,CAC9E,IAAM,EAAU,EAAW,EAAM,CAAM,EAEvC,GAAI,IAAc,IAAK,MAAO,YAAY,IAE1C,IAAM,EAAO,EAAU,MAAM,GAAG,EAAE,IAAI,KAAK,CACzC,IAAM,EAAM,SAAS,EAAE,KAAK,CAAC,EAC7B,OAAO,EAAU,IAAQ,EAC1B,EAED,GAAI,EAAK,SAAW,EAAG,MAAO,YAAY,IAC1C,GAAI,EAAK,SAAW,GAAK,CAAC,EAAK,SAAS,KAAK,GAAK,CAAC,EAAK,SAAS,KAAK,EACpE,MAAO,eAAe,IAExB,GAAI,EAAK,SAAW,EAAG,MAAO,aAAa,EAAK,SAAS,IACzD,MAAO,GAAG,EAAK,KAAK,KAAK,QAAQ,IAGnC,OAAO,EACP,KAAM,CACN,OAAO,GAIJ,SAAS,CAAkB,CAAC,EAAyB,CAC1D,IAAM,EAAO,IAAI,KAAK,CAAO,EACvB,EAAM,IAAI,KACV,EAAS,EAAK,QAAQ,EAAI,EAAI,QAAQ,EACtC,EAAY,KAAK,IAAI,CAAM,EAC3B,EAAW,EAAS,EAEpB,EAAU,KAAK,MAAM,EAAY,KAAK,EACtC,EAAQ,KAAK,MAAM,EAAY,OAAO,EACtC,EAAO,KAAK,MAAM,EAAY,QAAQ,EAEtC,EAAU,EAAK,mBAAmB,CAAC,EAAG,CAAE,KAAM,UAAW,OAAQ,SAAU,CAAC,EAE5E,EAAU,EAAK,aAAa,IAAM,EAAI,aAAa,EACnD,EAAW,IAAI,KAAK,CAAG,EAC7B,EAAS,QAAQ,EAAS,QAAQ,EAAI,CAAC,EACvC,IAAM,EAAa,EAAK,aAAa,IAAM,EAAS,aAAa,EAC3D,EAAY,IAAI,KAAK,CAAG,EAC9B,EAAU,QAAQ,EAAU,QAAQ,EAAI,CAAC,EACzC,IAAM,EAAc,EAAK,aAAa,IAAM,EAAU,aAAa,EAEnE,GAAI,EAAS,CACX,GAAI,EAAU,EAAG,OAAO,EAAW,MAAQ,WAC3C,GAAI,EAAU,GAAI,OAAO,EAAW,MAAM,UAAgB,KAAa,GAAG,YAC1E,OAAO,EAAW,MAAM,OAAW,KAAa,GAAG,SAGrD,GAAI,EAAY,MAAO,eAAe,IACtC,GAAI,EAAa,MAAO,gBAAgB,IAExC,GAAI,EAAO,EAET,MAAO,GADS,EAAU,EAAK,OAAO,SACd,IAG1B,OAAO,EAAK,mBAAmB,CAAC,EAAG,CAAE,MAAO,QAAS,IAAK,SAAU,CAAC,EAAI,OAAO",
8
+ "debugId": "8E2D9B056A9C318964756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{O as V}from"./App.e2kkda2a.js";import{U as D}from"./App.sd685nt9.js";import{$ as Kk,X as P,aa as v,da as i,ja as o,ma as d}from"./App.shfd8tp9.js";var J=P(Kk(),1);var q=P(v(),1);function Yk(){let{authFetch:K}=o(),{currentProjectId:X}=d(),{confirm:j,ConfirmDialog:E}=V(),[$,x]=J.useState([]),[A,c]=J.useState([]),[a,u]=J.useState(!0),[r,Y]=J.useState(!1),[H,C]=J.useState(null),[T,Q]=J.useState(new Set),[F,R]=J.useState(!1),[y,I]=J.useState(null),[w,f]=J.useState(null),[S,U]=J.useState({}),[M,N]=J.useState(""),[b,L]=J.useState(""),[g,B]=J.useState(""),Z=X&&X!=="all"&&X!=="unassigned"?X:null,n=Z?A.filter((k)=>k.projectId===Z):A,{events:p}=i({category:"test",limit:50}),_=J.useRef(new Set);J.useEffect(()=>{for(let k of p){if(_.current.has(k.id))continue;_.current.add(k.id);let z=k.data?.test_case_id;if(!z)continue;if(k.type==="test_started")U((G)=>({...G,[z]:{phase:"starting"}})),Q((G)=>new Set(G).add(z));else if(k.type==="test_planning")U((G)=>({...G,[z]:{phase:"planning"}}));else if(k.type==="test_executing"){let G=k.data?.agent_name;U((O)=>({...O,[z]:{phase:"executing",detail:G}}))}else if(k.type==="test_judging")U((G)=>({...G,[z]:{phase:"judging"}}));else if(k.type==="test_completed")U((G)=>{let O={...G};return delete O[z],O}),Q((G)=>{let O=new Set(G);return O.delete(z),O}),W()}if(_.current.size>500)_.current=new Set([..._.current].slice(-200))},[p]);let W=async()=>{try{let k=Z?`?project_id=${Z}`:"",z=await K(`/api/tests${k}`);if(z.ok)x(await z.json())}catch{}u(!1)},s=async()=>{try{let k=await K("/api/agents");if(k.ok){let z=await k.json();c((z.agents||z).map((G)=>({id:G.id,name:G.name,status:G.status,provider:G.provider,model:G.model,projectId:G.projectId||null})))}}catch{}};J.useEffect(()=>{Promise.all([W(),s()])},[X]);let l=()=>{C(null),N(""),L(""),B(""),Y(!0)},t=(k)=>{C(k),N(k.name),L(k.behavior||""),B(k.agent_id||""),Y(!0)},e=async()=>{if(!M||!b)return;let k={name:M,behavior:b,agent_id:g||null,project_id:Z||void 0};if(H)await K(`/api/tests/${H.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(k)});else await K("/api/tests",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(k)});Y(!1),W()},kk=async(k)=>{if(!await j("Delete this test case? Run history will also be deleted."))return;await K(`/api/tests/${k}`,{method:"DELETE"}),W()},qk=async(k)=>{Q((z)=>new Set(z).add(k));try{await K(`/api/tests/${k}/run`,{method:"POST"}),await W()}catch{}Q((z)=>{let G=new Set(z);return G.delete(k),G}),U((z)=>{let G={...z};return delete G[k],G})},zk=async()=>{R(!0);try{let k=$.map((z)=>z.id);Q(new Set(k)),await K("/api/tests/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({test_case_ids:k})}),await W()}catch{}Q(new Set),R(!1)},Gk=async(k)=>{try{let z=await K(`/api/tests/${k}/runs`);if(z.ok)I({testId:k,runs:await z.json()})}catch{}},h={starting:{label:"Starting",color:"bg-blue-900/50 text-blue-400 border-blue-500/30"},planning:{label:"Planning",color:"bg-purple-900/50 text-purple-400 border-purple-500/30"},executing:{label:"Executing",color:"bg-cyan-900/50 text-cyan-400 border-cyan-500/30"},judging:{label:"Judging",color:"bg-amber-900/50 text-amber-400 border-amber-500/30"}},m=(k)=>{return q.jsxDEV("span",{className:`px-2 py-0.5 rounded text-xs font-medium ${{passed:"bg-green-900/50 text-green-400",failed:"bg-red-900/50 text-red-400",error:"bg-yellow-900/50 text-yellow-400",running:"bg-blue-900/50 text-blue-400"}[k]||"bg-[var(--color-surface-raised)] text-[var(--color-text-muted)]"}`,children:k.toUpperCase()},void 0,!1,void 0,this)},Jk=(k)=>{let z=S[k];if(!z)return null;let G=h[z.phase]||h.starting;return q.jsxDEV("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs font-medium border ${G.color} animate-pulse`,children:[q.jsxDEV("span",{className:"w-1.5 h-1.5 rounded-full bg-current"},void 0,!1,void 0,this),G.label,z.detail?` · ${z.detail}`:""]},void 0,!0,void 0,this)};return q.jsxDEV("div",{className:"flex-1 overflow-auto p-6",children:[E,q.jsxDEV("div",{className:"flex items-center justify-between mb-6",children:[q.jsxDEV("div",{children:[q.jsxDEV("h1",{className:"text-xl font-bold",children:"Tests"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)] mt-1",children:"Describe behavior, AI handles the rest"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex gap-2",children:[$.length>0&&q.jsxDEV("button",{onClick:zk,disabled:F,className:"px-4 py-2 bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-[var(--color-text)] rounded text-sm font-medium transition disabled:opacity-50",children:F?"Running...":"Run All"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:l,className:"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-white rounded text-sm font-medium transition",children:"+ New Test"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),a?q.jsxDEV("div",{className:"text-[var(--color-text-muted)] text-sm",children:"Loading..."},void 0,!1,void 0,this):$.length===0?q.jsxDEV("div",{className:"text-center py-16",children:[q.jsxDEV("div",{className:"text-[var(--color-border-light)] text-4xl mb-4",children:q.jsxDEV("svg",{className:"w-12 h-12 mx-auto",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:q.jsxDEV("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:1.5,d:"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-[var(--color-text-muted)] mb-2",children:"No tests yet"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mb-4",children:"Describe what your agents should do and let AI verify it"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:l,className:"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-white rounded text-sm font-medium transition",children:"Create your first test"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):q.jsxDEV("div",{className:"space-y-3",children:$.map((k)=>q.jsxDEV("div",{className:"bg-[var(--color-surface)] card 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("span",{className:"font-medium text-sm",children:k.name},void 0,!1,void 0,this),S[k.id]?Jk(k.id):k.last_run&&q.jsxDEV(q.Fragment,{children:[m(k.last_run.status),k.last_run.score!=null&&q.jsxDEV("span",{className:"text-xs text-[var(--color-text-secondary)] font-mono",children:[k.last_run.score,"/10"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k.behavior&&q.jsxDEV("p",{className:"text-xs text-[var(--color-text-secondary)] mb-1.5 line-clamp-2",children:k.behavior},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-xs text-[var(--color-text-muted)] space-y-0.5",children:[q.jsxDEV("div",{children:["Agent:"," ",q.jsxDEV("span",{className:"text-[var(--color-text-secondary)]",children:k.agent_name||(k.last_run?.selected_agent_name?`${k.last_run.selected_agent_name} (auto-selected)`:"Auto (AI picks)")},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k.last_run?.generated_message&&q.jsxDEV("div",{className:"truncate",children:["Message: ",q.jsxDEV("span",{className:"text-[var(--color-text-secondary)]",children:['"',k.last_run.generated_message,'"']},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k.input_message&&!k.last_run?.generated_message&&q.jsxDEV("div",{className:"truncate",children:["Message: ",q.jsxDEV("span",{className:"text-[var(--color-text-secondary)]",children:['"',k.input_message,'"']},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k.last_run&&q.jsxDEV("div",{children:["Last run:"," ",q.jsxDEV("span",{className:"text-[var(--color-text-secondary)]",children:[k.last_run.duration_ms?`${(k.last_run.duration_ms/1000).toFixed(1)}s`:"---",k.last_run.judge_reasoning&&` --- "${k.last_run.judge_reasoning.slice(0,80)}${k.last_run.judge_reasoning.length>80?"...":""}"`]},void 0,!0,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:"flex items-center gap-1 ml-3 shrink-0",children:[q.jsxDEV("button",{onClick:()=>Gk(k.id),className:"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)] rounded transition",title:"View run history",children:"History"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>qk(k.id),disabled:T.has(k.id),className:"px-3 py-1 text-xs bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-[var(--color-text)] rounded transition disabled:opacity-50",children:T.has(k.id)?"Running...":"Run"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>t(k),className:"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)] rounded transition",children:"Edit"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>kk(k.id),className:"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-red-400 hover:bg-[var(--color-surface-raised)] rounded transition",children:"Delete"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},k.id,!1,void 0,this))},void 0,!1,void 0,this),y&&q.jsxDEV("div",{className:"mt-6",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-3",children:[q.jsxDEV("h2",{className:"text-sm font-bold text-[var(--color-text-secondary)]",children:"Run History"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>{I(null),f(null)},className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]",children:"Close"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y.runs.length===0?q.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)]",children:"No runs yet"},void 0,!1,void 0,this):q.jsxDEV("div",{className:"space-y-2",children:y.runs.map((k)=>q.jsxDEV("div",{className:"bg-[var(--color-bg-secondary)] border border-[var(--color-border)] rounded p-3",children:[q.jsxDEV("div",{className:"flex items-center justify-between cursor-pointer",onClick:()=>f(w===k.id?null:k.id),children:[q.jsxDEV("div",{className:"flex items-center gap-3",children:[m(k.status),q.jsxDEV("span",{className:"text-xs text-[var(--color-text-muted)]",children:k.duration_ms?`${(k.duration_ms/1000).toFixed(1)}s`:"---"},void 0,!1,void 0,this),k.score!=null&&q.jsxDEV("span",{className:"text-xs text-[var(--color-text-secondary)] font-mono",children:[k.score,"/10"]},void 0,!0,void 0,this),k.selected_agent_name&&q.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)]",children:["Agent: ",k.selected_agent_name]},void 0,!0,void 0,this),q.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)]",children:new Date(k.created_at).toLocaleString()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)]",children:w===k.id?"---":"+"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w===k.id&&q.jsxDEV("div",{className:"mt-3 space-y-2",children:[k.planner_reasoning&&q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"text-xs text-[var(--color-text-muted)] mb-1",children:"Planner:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded",children:[k.selected_agent_name&&q.jsxDEV("span",{className:"text-[var(--color-accent)]",children:k.selected_agent_name},void 0,!1,void 0,this),k.selected_agent_name&&" --- ",k.planner_reasoning]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k.generated_message&&q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"text-xs text-[var(--color-text-muted)] mb-1",children:"Generated Message:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded",children:['"',k.generated_message,'"']},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k.judge_reasoning&&q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"text-xs text-[var(--color-text-muted)] mb-1",children:"Judge:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded",children:k.judge_reasoning},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k.error&&q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"text-xs text-red-400 mb-1",children:"Error:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-red-300 bg-[var(--color-bg)] p-2 rounded",children:k.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k.agent_response&&q.jsxDEV("div",{children:[q.jsxDEV("div",{className:"text-xs text-[var(--color-text-muted)] mb-1",children:"Agent Response (Thread):"},void 0,!1,void 0,this),q.jsxDEV("pre",{className:"text-xs text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded overflow-auto max-h-64",children:k.agent_response},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},k.id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),r&&q.jsxDEV("div",{className:"fixed inset-0 bg-black/60 z-50 flex items-center justify-center",onClick:()=>Y(!1),children:q.jsxDEV("div",{className:"bg-[var(--color-surface)] card w-full max-w-lg mx-4 p-6",onClick:(k)=>k.stopPropagation(),children:[q.jsxDEV("h2",{className:"text-lg font-bold mb-4",children:H?"Edit Test":"New Test"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"space-y-4",children:[q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[var(--color-text-muted)] mb-1",children:"Name"},void 0,!1,void 0,this),q.jsxDEV("input",{value:M,onChange:(k)=>N(k.target.value),placeholder:"e.g. Social Media Posting",className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 text-sm focus:outline-none focus:border-[var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[var(--color-text-muted)] mb-1",children:"Behavior"},void 0,!1,void 0,this),q.jsxDEV("textarea",{value:b,onChange:(k)=>L(k.target.value),placeholder:"Describe what should happen, e.g. 'When asked to post on social media, the agent creates a proper post with relevant hashtags and confirms it was published'",rows:3,className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 text-sm focus:outline-none focus:border-[var(--color-accent)] resize-none"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"AI will generate the test message and evaluate results based on this"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[var(--color-text-muted)] mb-1",children:"Agent"},void 0,!1,void 0,this),q.jsxDEV(D,{value:g,onChange:B,placeholder:"Auto (AI picks the best agent)",options:n.map((k)=>({value:k.id,label:`${k.name} (${k.status})`}))},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"Leave empty to let AI choose the right agent"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex justify-end gap-2 mt-6",children:[q.jsxDEV("button",{onClick:()=>Y(!1),className:"px-4 py-2 text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:e,disabled:!M||!b,className:"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-white rounded text-sm font-medium transition",children:H?"Save":"Create"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}
2
+ export{Yk as M};
3
+
4
+ //# debugId=2D14C6A7BC29E53364756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/tests/TestsPage.tsx"],
4
+ "sourcesContent": [
5
+ "import React, { useState, useEffect, useRef } from \"react\";\nimport { useAuth, useProjects } from \"../../context\";\nimport { useTelemetry } from \"../../context/TelemetryContext\";\nimport { useConfirm } from \"../common/Modal\";\nimport { Select } from \"../common/Select\";\n\ninterface TestCase {\n id: string;\n name: string;\n description: string | null;\n behavior: string | null;\n agent_id: string | null;\n input_message: string | null;\n eval_criteria: string;\n timeout_ms: number;\n project_id: string | null;\n created_at: string;\n updated_at: string;\n agent_name: string | null;\n agent_status: string | null;\n last_run: {\n id: string;\n status: string;\n score: number | null;\n duration_ms: number | null;\n judge_reasoning: string | null;\n generated_message: string | null;\n selected_agent_id: string | null;\n selected_agent_name: string | null;\n planner_reasoning: string | null;\n created_at: string;\n } | null;\n}\n\ninterface TestRun {\n id: string;\n test_case_id: string;\n status: string;\n score: number | null;\n agent_response: string | null;\n judge_reasoning: string | null;\n duration_ms: number | null;\n error: string | null;\n generated_message: string | null;\n selected_agent_id: string | null;\n selected_agent_name: string | null;\n planner_reasoning: string | null;\n created_at: string;\n}\n\ninterface AgentOption {\n id: string;\n name: string;\n status: string;\n provider: string;\n model: string;\n projectId: string | null;\n}\n\nexport function TestsPage() {\n const { authFetch } = useAuth();\n const { currentProjectId } = useProjects();\n const { confirm, ConfirmDialog } = useConfirm();\n\n const [tests, setTests] = useState<TestCase[]>([]);\n const [agents, setAgents] = useState<AgentOption[]>([]);\n const [loading, setLoading] = useState(true);\n const [showForm, setShowForm] = useState(false);\n const [editingTest, setEditingTest] = useState<TestCase | null>(null);\n const [runningTests, setRunningTests] = useState<Set<string>>(new Set());\n const [runningAll, setRunningAll] = useState(false);\n const [selectedRuns, setSelectedRuns] = useState<{ testId: string; runs: TestRun[] } | null>(null);\n const [expandedRun, setExpandedRun] = useState<string | null>(null);\n // Live test status from telemetry SSE\n const [liveStatus, setLiveStatus] = useState<Record<string, { phase: string; detail?: string }>>({});\n\n // Form state\n const [formName, setFormName] = useState(\"\");\n const [formBehavior, setFormBehavior] = useState(\"\");\n const [formAgentId, setFormAgentId] = useState(\"\"); // empty = auto\n\n const activeProjectId = currentProjectId && currentProjectId !== \"all\" && currentProjectId !== \"unassigned\"\n ? currentProjectId : null;\n\n // Filter agents to current project\n const projectAgents = activeProjectId\n ? agents.filter(a => a.projectId === activeProjectId)\n : agents;\n\n // Subscribe to test telemetry events for live status\n const { events: testEvents } = useTelemetry({ category: \"test\", limit: 50 });\n const processedEventsRef = useRef<Set<string>>(new Set());\n\n useEffect(() => {\n for (const evt of testEvents) {\n if (processedEventsRef.current.has(evt.id)) continue;\n processedEventsRef.current.add(evt.id);\n\n const testCaseId = evt.data?.test_case_id as string;\n if (!testCaseId) continue;\n\n if (evt.type === \"test_started\") {\n setLiveStatus(prev => ({ ...prev, [testCaseId]: { phase: \"starting\" } }));\n setRunningTests(prev => new Set(prev).add(testCaseId));\n } else if (evt.type === \"test_planning\") {\n setLiveStatus(prev => ({ ...prev, [testCaseId]: { phase: \"planning\" } }));\n } else if (evt.type === \"test_executing\") {\n const agentName = evt.data?.agent_name as string;\n setLiveStatus(prev => ({ ...prev, [testCaseId]: { phase: \"executing\", detail: agentName } }));\n } else if (evt.type === \"test_judging\") {\n setLiveStatus(prev => ({ ...prev, [testCaseId]: { phase: \"judging\" } }));\n } else if (evt.type === \"test_completed\") {\n setLiveStatus(prev => {\n const next = { ...prev };\n delete next[testCaseId];\n return next;\n });\n setRunningTests(prev => {\n const next = new Set(prev);\n next.delete(testCaseId);\n return next;\n });\n // Refresh test list to get updated results\n fetchTests();\n }\n }\n // Cap processed set to prevent unbounded growth\n if (processedEventsRef.current.size > 500) {\n processedEventsRef.current = new Set([...processedEventsRef.current].slice(-200));\n }\n }, [testEvents]);\n\n const fetchTests = async () => {\n try {\n const params = activeProjectId ? `?project_id=${activeProjectId}` : \"\";\n const res = await authFetch(`/api/tests${params}`);\n if (res.ok) setTests(await res.json());\n } catch { /* ignore */ }\n setLoading(false);\n };\n\n const fetchAgents = async () => {\n try {\n const res = await authFetch(\"/api/agents\");\n if (res.ok) {\n const data = await res.json();\n setAgents((data.agents || data).map((a: any) => ({\n id: a.id,\n name: a.name,\n status: a.status,\n provider: a.provider,\n model: a.model,\n projectId: a.projectId || null,\n })));\n }\n } catch { /* ignore */ }\n };\n\n useEffect(() => {\n Promise.all([fetchTests(), fetchAgents()]);\n }, [currentProjectId]);\n\n const openCreate = () => {\n setEditingTest(null);\n setFormName(\"\");\n setFormBehavior(\"\");\n setFormAgentId(\"\");\n setShowForm(true);\n };\n\n const openEdit = (tc: TestCase) => {\n setEditingTest(tc);\n setFormName(tc.name);\n setFormBehavior(tc.behavior || \"\");\n setFormAgentId(tc.agent_id || \"\");\n setShowForm(true);\n };\n\n const handleSave = async () => {\n if (!formName || !formBehavior) return;\n\n const body: any = {\n name: formName,\n behavior: formBehavior,\n agent_id: formAgentId || null,\n project_id: activeProjectId || undefined,\n };\n\n if (editingTest) {\n await authFetch(`/api/tests/${editingTest.id}`, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n } else {\n await authFetch(\"/api/tests\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n }\n\n setShowForm(false);\n fetchTests();\n };\n\n const handleDelete = async (id: string) => {\n const ok = await confirm(\"Delete this test case? Run history will also be deleted.\");\n if (!ok) return;\n await authFetch(`/api/tests/${id}`, { method: \"DELETE\" });\n fetchTests();\n };\n\n const handleRun = async (id: string) => {\n setRunningTests(prev => new Set(prev).add(id));\n try {\n await authFetch(`/api/tests/${id}/run`, { method: \"POST\" });\n // Telemetry SSE handles live status updates; final refresh on completion\n await fetchTests();\n } catch { /* ignore */ }\n // Cleanup in case telemetry didn't fire\n setRunningTests(prev => {\n const next = new Set(prev);\n next.delete(id);\n return next;\n });\n setLiveStatus(prev => {\n const next = { ...prev };\n delete next[id];\n return next;\n });\n };\n\n const handleRunAll = async () => {\n setRunningAll(true);\n try {\n const ids = tests.map(t => t.id);\n setRunningTests(new Set(ids));\n await authFetch(\"/api/tests/run\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ test_case_ids: ids }),\n });\n await fetchTests();\n } catch { /* ignore */ }\n setRunningTests(new Set());\n setRunningAll(false);\n };\n\n const viewRuns = async (testId: string) => {\n try {\n const res = await authFetch(`/api/tests/${testId}/runs`);\n if (res.ok) {\n setSelectedRuns({ testId, runs: await res.json() });\n }\n } catch { /* ignore */ }\n };\n\n const phaseLabels: Record<string, { label: string; color: string }> = {\n starting: { label: \"Starting\", color: \"bg-blue-900/50 text-blue-400 border-blue-500/30\" },\n planning: { label: \"Planning\", color: \"bg-purple-900/50 text-purple-400 border-purple-500/30\" },\n executing: { label: \"Executing\", color: \"bg-cyan-900/50 text-cyan-400 border-cyan-500/30\" },\n judging: { label: \"Judging\", color: \"bg-amber-900/50 text-amber-400 border-amber-500/30\" },\n };\n\n const statusBadge = (status: string) => {\n const colors: Record<string, string> = {\n passed: \"bg-green-900/50 text-green-400\",\n failed: \"bg-red-900/50 text-red-400\",\n error: \"bg-yellow-900/50 text-yellow-400\",\n running: \"bg-blue-900/50 text-blue-400\",\n };\n return (\n <span className={`px-2 py-0.5 rounded text-xs font-medium ${colors[status] || \"bg-[var(--color-surface-raised)] text-[var(--color-text-muted)]\"}`}>\n {status.toUpperCase()}\n </span>\n );\n };\n\n const liveBadge = (testCaseId: string) => {\n const live = liveStatus[testCaseId];\n if (!live) return null;\n const phase = phaseLabels[live.phase] || phaseLabels.starting;\n return (\n <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs font-medium border ${phase.color} animate-pulse`}>\n <span className=\"w-1.5 h-1.5 rounded-full bg-current\" />\n {phase.label}{live.detail ? ` \\u00b7 ${live.detail}` : \"\"}\n </span>\n );\n };\n\n return (\n <div className=\"flex-1 overflow-auto p-6\">\n {ConfirmDialog}\n\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div>\n <h1 className=\"text-xl font-bold\">Tests</h1>\n <p className=\"text-sm text-[var(--color-text-muted)] mt-1\">\n Describe behavior, AI handles the rest\n </p>\n </div>\n <div className=\"flex gap-2\">\n {tests.length > 0 && (\n <button\n onClick={handleRunAll}\n disabled={runningAll}\n className=\"px-4 py-2 bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-[var(--color-text)] rounded text-sm font-medium transition disabled:opacity-50\"\n >\n {runningAll ? \"Running...\" : \"Run All\"}\n </button>\n )}\n <button\n onClick={openCreate}\n className=\"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-white rounded text-sm font-medium transition\"\n >\n + New Test\n </button>\n </div>\n </div>\n\n {/* Test list */}\n {loading ? (\n <div className=\"text-[var(--color-text-muted)] text-sm\">Loading...</div>\n ) : tests.length === 0 ? (\n <div className=\"text-center py-16\">\n <div className=\"text-[var(--color-border-light)] text-4xl mb-4\">\n <svg className=\"w-12 h-12 mx-auto\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\" />\n </svg>\n </div>\n <p className=\"text-[var(--color-text-muted)] mb-2\">No tests yet</p>\n <p className=\"text-xs text-[var(--color-text-faint)] mb-4\">Describe what your agents should do and let AI verify it</p>\n <button\n onClick={openCreate}\n className=\"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-white rounded text-sm font-medium transition\"\n >\n Create your first test\n </button>\n </div>\n ) : (\n <div className=\"space-y-3\">\n {tests.map(tc => (\n <div key={tc.id} className=\"bg-[var(--color-surface)] card 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 <span className=\"font-medium text-sm\">{tc.name}</span>\n {liveStatus[tc.id]\n ? liveBadge(tc.id)\n : tc.last_run && (<>\n {statusBadge(tc.last_run.status)}\n {tc.last_run.score != null && (\n <span className=\"text-xs text-[var(--color-text-secondary)] font-mono\">{tc.last_run.score}/10</span>\n )}\n </>)\n }\n </div>\n {tc.behavior && (\n <p className=\"text-xs text-[var(--color-text-secondary)] mb-1.5 line-clamp-2\">{tc.behavior}</p>\n )}\n <div className=\"text-xs text-[var(--color-text-muted)] space-y-0.5\">\n <div>\n Agent:{\" \"}\n <span className=\"text-[var(--color-text-secondary)]\">\n {tc.agent_name || (tc.last_run?.selected_agent_name\n ? `${tc.last_run.selected_agent_name} (auto-selected)`\n : \"Auto (AI picks)\")}\n </span>\n </div>\n {tc.last_run?.generated_message && (\n <div className=\"truncate\">\n Message: <span className=\"text-[var(--color-text-secondary)]\">\"{tc.last_run.generated_message}\"</span>\n </div>\n )}\n {tc.input_message && !tc.last_run?.generated_message && (\n <div className=\"truncate\">\n Message: <span className=\"text-[var(--color-text-secondary)]\">\"{tc.input_message}\"</span>\n </div>\n )}\n {tc.last_run && (\n <div>\n Last run:{\" \"}\n <span className=\"text-[var(--color-text-secondary)]\">\n {tc.last_run.duration_ms ? `${(tc.last_run.duration_ms / 1000).toFixed(1)}s` : \"---\"}\n {tc.last_run.judge_reasoning && ` --- \"${tc.last_run.judge_reasoning.slice(0, 80)}${tc.last_run.judge_reasoning.length > 80 ? \"...\" : \"\"}\"`}\n </span>\n </div>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-1 ml-3 shrink-0\">\n <button\n onClick={() => viewRuns(tc.id)}\n className=\"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)] rounded transition\"\n title=\"View run history\"\n >\n History\n </button>\n <button\n onClick={() => handleRun(tc.id)}\n disabled={runningTests.has(tc.id)}\n className=\"px-3 py-1 text-xs bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-[var(--color-text)] rounded transition disabled:opacity-50\"\n >\n {runningTests.has(tc.id) ? \"Running...\" : \"Run\"}\n </button>\n <button\n onClick={() => openEdit(tc)}\n className=\"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-raised)] rounded transition\"\n >\n Edit\n </button>\n <button\n onClick={() => handleDelete(tc.id)}\n className=\"px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-red-400 hover:bg-[var(--color-surface-raised)] rounded transition\"\n >\n Delete\n </button>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Run History Panel */}\n {selectedRuns && (\n <div className=\"mt-6\">\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-sm font-bold text-[var(--color-text-secondary)]\">Run History</h2>\n <button\n onClick={() => { setSelectedRuns(null); setExpandedRun(null); }}\n className=\"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]\"\n >\n Close\n </button>\n </div>\n {selectedRuns.runs.length === 0 ? (\n <p className=\"text-sm text-[var(--color-text-muted)]\">No runs yet</p>\n ) : (\n <div className=\"space-y-2\">\n {selectedRuns.runs.map(run => (\n <div key={run.id} className=\"bg-[var(--color-bg-secondary)] border border-[var(--color-border)] rounded p-3\">\n <div\n className=\"flex items-center justify-between cursor-pointer\"\n onClick={() => setExpandedRun(expandedRun === run.id ? null : run.id)}\n >\n <div className=\"flex items-center gap-3\">\n {statusBadge(run.status)}\n <span className=\"text-xs text-[var(--color-text-muted)]\">\n {run.duration_ms ? `${(run.duration_ms / 1000).toFixed(1)}s` : \"---\"}\n </span>\n {run.score != null && (\n <span className=\"text-xs text-[var(--color-text-secondary)] font-mono\">{run.score}/10</span>\n )}\n {run.selected_agent_name && (\n <span className=\"text-xs text-[var(--color-text-faint)]\">\n Agent: {run.selected_agent_name}\n </span>\n )}\n <span className=\"text-xs text-[var(--color-text-faint)]\">\n {new Date(run.created_at).toLocaleString()}\n </span>\n </div>\n <span className=\"text-xs text-[var(--color-text-faint)]\">{expandedRun === run.id ? \"---\" : \"+\"}</span>\n </div>\n {expandedRun === run.id && (\n <div className=\"mt-3 space-y-2\">\n {run.planner_reasoning && (\n <div>\n <div className=\"text-xs text-[var(--color-text-muted)] mb-1\">Planner:</div>\n <div className=\"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded\">\n {run.selected_agent_name && <span className=\"text-[var(--color-accent)]\">{run.selected_agent_name}</span>}\n {run.selected_agent_name && \" --- \"}\n {run.planner_reasoning}\n </div>\n </div>\n )}\n {run.generated_message && (\n <div>\n <div className=\"text-xs text-[var(--color-text-muted)] mb-1\">Generated Message:</div>\n <div className=\"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded\">\"{run.generated_message}\"</div>\n </div>\n )}\n {run.judge_reasoning && (\n <div>\n <div className=\"text-xs text-[var(--color-text-muted)] mb-1\">Judge:</div>\n <div className=\"text-sm text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded\">{run.judge_reasoning}</div>\n </div>\n )}\n {run.error && (\n <div>\n <div className=\"text-xs text-red-400 mb-1\">Error:</div>\n <div className=\"text-sm text-red-300 bg-[var(--color-bg)] p-2 rounded\">{run.error}</div>\n </div>\n )}\n {run.agent_response && (\n <div>\n <div className=\"text-xs text-[var(--color-text-muted)] mb-1\">Agent Response (Thread):</div>\n <pre className=\"text-xs text-[var(--color-text-secondary)] bg-[var(--color-bg)] p-2 rounded overflow-auto max-h-64\">\n {run.agent_response}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Create/Edit Form Modal */}\n {showForm && (\n <div className=\"fixed inset-0 bg-black/60 z-50 flex items-center justify-center\" onClick={() => setShowForm(false)}>\n <div className=\"bg-[var(--color-surface)] card w-full max-w-lg mx-4 p-6\" onClick={e => e.stopPropagation()}>\n <h2 className=\"text-lg font-bold mb-4\">{editingTest ? \"Edit Test\" : \"New Test\"}</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-xs text-[var(--color-text-muted)] mb-1\">Name</label>\n <input\n value={formName}\n onChange={e => setFormName(e.target.value)}\n placeholder=\"e.g. Social Media Posting\"\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 text-sm focus:outline-none focus:border-[var(--color-accent)]\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs text-[var(--color-text-muted)] mb-1\">Behavior</label>\n <textarea\n value={formBehavior}\n onChange={e => setFormBehavior(e.target.value)}\n placeholder=\"Describe what should happen, e.g. 'When asked to post on social media, the agent creates a proper post with relevant hashtags and confirms it was published'\"\n rows={3}\n className=\"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 text-sm focus:outline-none focus:border-[var(--color-accent)] resize-none\"\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">AI will generate the test message and evaluate results based on this</p>\n </div>\n\n <div>\n <label className=\"block text-xs text-[var(--color-text-muted)] mb-1\">Agent</label>\n <Select\n value={formAgentId}\n onChange={setFormAgentId}\n placeholder=\"Auto (AI picks the best agent)\"\n options={projectAgents.map(a => ({\n value: a.id,\n label: `${a.name} (${a.status})`,\n }))}\n />\n <p className=\"text-xs text-[var(--color-text-faint)] mt-1\">Leave empty to let AI choose the right agent</p>\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n onClick={() => setShowForm(false)}\n className=\"px-4 py-2 text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={!formName || !formBehavior}\n className=\"px-4 py-2 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-white rounded text-sm font-medium transition\"\n >\n {editingTest ? \"Save\" : \"Create\"}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "2D14C6A7BC29E53364756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{$ as P,X as L,aa as N}from"./App.shfd8tp9.js";var z=L(P(),1),w=L(N(),1);function U({children:q,onClose:y}){return w.jsxDEV("div",{className:"fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4",children:w.jsxDEV("div",{className:"bg-[var(--color-surface)] card p-6 w-full max-w-xl lg:max-w-2xl max-h-[90vh] overflow-y-auto",children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Q({title:q,message:y,confirmText:F="Confirm",cancelText:B="Cancel",confirmVariant:G="danger",onConfirm:I,onCancel:J}){return w.jsxDEV("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:w.jsxDEV("div",{className:"bg-[var(--color-surface)] card p-6 w-full max-w-sm",children:[q&&w.jsxDEV("h3",{className:"font-medium mb-2",children:q},void 0,!1,void 0,this),w.jsxDEV("p",{className:"text-sm text-[var(--color-text)] mb-4",children:y},void 0,!1,void 0,this),w.jsxDEV("div",{className:"flex gap-2",children:[w.jsxDEV("button",{onClick:J,className:"flex-1 text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] btn px-4 py-2 transition",children:B},void 0,!1,void 0,this),w.jsxDEV("button",{onClick:I,className:`flex-1 text-sm text-white px-4 py-2 btn transition ${G==="danger"?"bg-red-500 hover:bg-red-600":"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)]"}`,children:F},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function R({title:q,message:y,buttonText:F="OK",variant:B="info",onClose:G}){let I={error:"bg-red-500/20 text-red-400",success:"bg-green-500/20 text-green-400",info:"bg-blue-500/20 text-blue-400"},J={error:"✕",success:"✓",info:"ℹ"};return w.jsxDEV("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",children:w.jsxDEV("div",{className:"bg-[var(--color-surface)] card p-6 w-full max-w-sm text-center",children:[w.jsxDEV("div",{className:`w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-3 ${I[B]}`,children:w.jsxDEV("span",{className:"text-xl",children:J[B]},void 0,!1,void 0,this)},void 0,!1,void 0,this),q&&w.jsxDEV("h3",{className:"font-medium mb-2",children:q},void 0,!1,void 0,this),w.jsxDEV("p",{className:"text-sm text-[var(--color-text)] mb-4",children:y},void 0,!1,void 0,this),w.jsxDEV("button",{onClick:G,className:"w-full text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] px-4 py-2 btn transition",children:F},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function W(){let[q,y]=z.useState(null),F=z.useCallback((J,K={})=>{return new Promise((O)=>{y({message:J,options:K,resolve:O})})},[]),B=z.useCallback(()=>{q?.resolve(!0),y(null)},[q]),G=z.useCallback(()=>{q?.resolve(!1),y(null)},[q]),I=q?w.jsxDEV(Q,{title:q.options.title,message:q.message,confirmText:q.options.confirmText,cancelText:q.options.cancelText,confirmVariant:q.options.confirmVariant,onConfirm:B,onCancel:G},void 0,!1,void 0,this):null;return{confirm:F,ConfirmDialog:I}}function X(){let[q,y]=z.useState(null),F=z.useCallback((I,J={})=>{return new Promise((K)=>{y({message:I,options:J,resolve:K})})},[]),B=z.useCallback(()=>{q?.resolve(),y(null)},[q]),G=q?w.jsxDEV(R,{title:q.options.title,message:q.message,buttonText:q.options.buttonText,variant:q.options.variant,onClose:B},void 0,!1,void 0,this):null;return{alert:F,AlertDialog:G}}
2
+ export{U as N,W as O,X as P};
3
+
4
+ //# debugId=47B6BB0942493C6364756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/common/Modal.tsx"],
4
+ "sourcesContent": [
5
+ "import React from \"react\";\n\ninterface ModalProps {\n children: React.ReactNode;\n onClose?: () => void;\n}\n\nexport function Modal({ children, onClose }: ModalProps) {\n return (\n <div className=\"fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4\">\n <div className=\"bg-[var(--color-surface)] card p-6 w-full max-w-xl lg:max-w-2xl max-h-[90vh] overflow-y-auto\">\n {children}\n </div>\n </div>\n );\n}\n\n// Confirmation Modal - replaces browser confirm()\ninterface ConfirmModalProps {\n title?: string;\n message: string;\n confirmText?: string;\n cancelText?: string;\n confirmVariant?: \"danger\" | \"primary\";\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function ConfirmModal({\n title,\n message,\n confirmText = \"Confirm\",\n cancelText = \"Cancel\",\n confirmVariant = \"danger\",\n onConfirm,\n onCancel,\n}: ConfirmModalProps) {\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4\">\n <div className=\"bg-[var(--color-surface)] card p-6 w-full max-w-sm\">\n {title && <h3 className=\"font-medium mb-2\">{title}</h3>}\n <p className=\"text-sm text-[var(--color-text)] mb-4\">{message}</p>\n <div className=\"flex gap-2\">\n <button\n onClick={onCancel}\n className=\"flex-1 text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] btn px-4 py-2 transition\"\n >\n {cancelText}\n </button>\n <button\n onClick={onConfirm}\n className={`flex-1 text-sm text-white px-4 py-2 btn transition ${\n confirmVariant === \"danger\"\n ? \"bg-red-500 hover:bg-red-600\"\n : \"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)]\"\n }`}\n >\n {confirmText}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// Alert Modal - replaces browser alert()\ninterface AlertModalProps {\n title?: string;\n message: string;\n buttonText?: string;\n variant?: \"error\" | \"success\" | \"info\";\n onClose: () => void;\n}\n\nexport function AlertModal({\n title,\n message,\n buttonText = \"OK\",\n variant = \"info\",\n onClose,\n}: AlertModalProps) {\n const iconColors = {\n error: \"bg-red-500/20 text-red-400\",\n success: \"bg-green-500/20 text-green-400\",\n info: \"bg-blue-500/20 text-blue-400\",\n };\n\n const icons = {\n error: \"✕\",\n success: \"✓\",\n info: \"ℹ\",\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4\">\n <div className=\"bg-[var(--color-surface)] card p-6 w-full max-w-sm text-center\">\n <div\n className={`w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-3 ${iconColors[variant]}`}\n >\n <span className=\"text-xl\">{icons[variant]}</span>\n </div>\n {title && <h3 className=\"font-medium mb-2\">{title}</h3>}\n <p className=\"text-sm text-[var(--color-text)] mb-4\">{message}</p>\n <button\n onClick={onClose}\n className=\"w-full text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] px-4 py-2 btn transition\"\n >\n {buttonText}\n </button>\n </div>\n </div>\n );\n}\n\n// Hook for using confirmation dialogs\nimport { useState, useCallback } from \"react\";\n\ninterface UseConfirmOptions {\n title?: string;\n confirmText?: string;\n cancelText?: string;\n confirmVariant?: \"danger\" | \"primary\";\n}\n\nexport function useConfirm() {\n const [state, setState] = useState<{\n message: string;\n options: UseConfirmOptions;\n resolve: (value: boolean) => void;\n } | null>(null);\n\n const confirm = useCallback((message: string, options: UseConfirmOptions = {}) => {\n return new Promise<boolean>((resolve) => {\n setState({ message, options, resolve });\n });\n }, []);\n\n const handleConfirm = useCallback(() => {\n state?.resolve(true);\n setState(null);\n }, [state]);\n\n const handleCancel = useCallback(() => {\n state?.resolve(false);\n setState(null);\n }, [state]);\n\n const ConfirmDialog = state ? (\n <ConfirmModal\n title={state.options.title}\n message={state.message}\n confirmText={state.options.confirmText}\n cancelText={state.options.cancelText}\n confirmVariant={state.options.confirmVariant}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n ) : null;\n\n return { confirm, ConfirmDialog };\n}\n\n// Hook for using alert dialogs\ninterface UseAlertOptions {\n title?: string;\n buttonText?: string;\n variant?: \"error\" | \"success\" | \"info\";\n}\n\nexport function useAlert() {\n const [state, setState] = useState<{\n message: string;\n options: UseAlertOptions;\n resolve: () => void;\n } | null>(null);\n\n const alert = useCallback((message: string, options: UseAlertOptions = {}) => {\n return new Promise<void>((resolve) => {\n setState({ message, options, resolve });\n });\n }, []);\n\n const handleClose = useCallback(() => {\n state?.resolve();\n setState(null);\n }, [state]);\n\n const AlertDialog = state ? (\n <AlertModal\n title={state.options.title}\n message={state.message}\n buttonText={state.options.buttonText}\n variant={state.options.variant}\n onClose={handleClose}\n />\n ) : null;\n\n return { alert, AlertDialog };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "47B6BB0942493C6364756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,13 @@
1
+ import{O as Oz,P as Wz}from"./App.e2kkda2a.js";import{U as j}from"./App.sd685nt9.js";import{$ as Qz,X as n,aa as zz,ja as Jz,ma as Kz}from"./App.shfd8tp9.js";var W=n(Qz(),1);var z=n(zz(),1);function Rz(){let{authFetch:K}=Jz(),{projects:Z,currentProjectId:Y}=Kz(),[B,N]=W.useState([]),[y,M]=W.useState(!0),[X,U]=W.useState("installed"),[G,Q]=W.useState(!1),[C,H]=W.useState(!1),[v,T]=W.useState(null),{confirm:f,ConfirmDialog:w}=Oz(),{alert:P,AlertDialog:d}=Wz(),_=Z.length>0,[m,p]=W.useState(""),[h,Xz]=W.useState([]),[c,r]=W.useState(!1),[Yz,o]=W.useState(null),[a,i]=W.useState(""),[R,t]=W.useState([]),[I,u]=W.useState(!1),[V,b]=W.useState(null),[q,l]=W.useState(null),[e,S]=W.useState(null),[x,Zz]=W.useState(Y&&Y!=="unassigned"?Y:null),D=B.filter((J)=>{if(!Y)return!0;if(Y==="unassigned")return J.project_id===null;return J.project_id===null||J.project_id===Y}),F=async()=>{try{let O=await(await K("/api/skills")).json();N(O.skills||[])}catch(J){console.error("Failed to fetch skills:",J)}M(!1)},E=async(J)=>{r(!0);try{let O=J!==void 0?J:m,$=O?`/api/skills/marketplace/search?q=${encodeURIComponent(O)}`:"/api/skills/marketplace/featured",A=await(await K($)).json();Xz(A.skills||[])}catch(O){console.error("Failed to search marketplace:",O)}r(!1)};W.useEffect(()=>{F()},[K]),W.useEffect(()=>{if(X==="marketplace"&&h.length===0)E("")},[X]);let _z=async(J)=>{try{await K(`/api/skills/${J}/toggle`,{method:"POST"}),F()}catch(O){console.error("Failed to toggle skill:",O)}},$z=async(J)=>{if(!await f("Delete this skill?",{confirmText:"Delete",title:"Delete Skill"}))return;try{if(await K(`/api/skills/${J}`,{method:"DELETE"}),v?.id===J)T(null);F()}catch($){console.error("Failed to delete skill:",$)}},Bz=async(J)=>{o(J.id);try{let O=await K(`/api/skills/marketplace/${J.id}/install`,{method:"POST"}),$=await O.json();if(O.ok)await P(`Installed "${J.name}" successfully!`,{title:"Skill Installed"}),F(),U("installed");else await P($.error||"Failed to install skill",{title:"Installation Failed"})}catch(O){console.error("Failed to install skill:",O),await P("Failed to install skill",{title:"Error"})}o(null)},g=(J)=>B.some((O)=>O.name===J),s=async(J)=>{let O=J||a;if(!O.trim())return;let $="",L="";if(O.includes("github.com")){let A=O.match(/github\.com\/([^/]+)\/([^/]+)/);if(A)$=A[1],L=A[2].replace(/\.git$/,"")}else if(O.includes("/")){let A=O.split("/");$=A[0],L=A[1]}if(!$||!L){b("Invalid repo format. Use 'owner/repo' or GitHub URL");return}u(!0),b(null),t([]),l(null);try{let A=await K(`/api/skills/github/${$}/${L}`),k=await A.json();if(!A.ok){b(k.error||"Failed to fetch repository"),u(!1);return}t(k.skills||[]),l(k.repo||null)}catch(A){b("Failed to fetch repository")}u(!1)},Nz=async(J)=>{if(!q)return;S(J.name);try{let O=await K("/api/skills/github/install",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({owner:q.owner,repo:q.repo,skillName:J.name,downloadUrl:J.downloadUrl,projectId:x})}),$=await O.json();if(O.ok)await P(`Installed "${J.name}" successfully!`,{title:"Skill Installed"}),F();else await P($.error||"Failed to install skill",{title:"Installation Failed",variant:"error"})}catch(O){await P("Failed to install skill",{title:"Error",variant:"error"})}S(null)},Uz=async()=>{if(!q||R.length===0)return;let J=R.filter((L)=>!g(L.name));if(J.length===0){await P("All skills are already installed",{title:"Info"});return}if(!await f(`Install ${J.length} skill(s) from ${q.owner}/${q.repo}?`,{confirmText:"Install All",title:"Install Skills"}))return;let $=0;for(let L of J){S(L.name);try{if((await K("/api/skills/github/install",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({owner:q.owner,repo:q.repo,skillName:L.name,downloadUrl:L.downloadUrl,projectId:x})})).ok)$++}catch(A){}}S(null),F(),await P(`Installed ${$} of ${J.length} skills`,{title:"Installation Complete"})};return z.jsxDEV(z.Fragment,{children:[w,d,z.jsxDEV("div",{className:"flex-1 overflow-auto p-6",children:z.jsxDEV("div",{className:"max-w-6xl",children:[z.jsxDEV("div",{className:"flex items-center justify-between mb-6",children:[z.jsxDEV("div",{children:[z.jsxDEV("h1",{className:"text-2xl font-semibold mb-1",children:"Skills"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-[var(--color-text-muted)]",children:"Manage agent skills - instructions that teach agents how to perform tasks."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X==="installed"&&z.jsxDEV("div",{className:"flex gap-2",children:[z.jsxDEV("button",{onClick:()=>H(!0),className:"bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-white px-4 py-2 rounded font-medium transition border border-[var(--color-border-light)]",children:"Import"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:()=>Q(!0),className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-black px-4 py-2 rounded font-medium transition",children:"+ Create Skill"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex gap-1 mb-6 bg-[var(--color-surface)] card p-1 w-fit",children:[z.jsxDEV("button",{onClick:()=>U("installed"),className:`px-4 py-2 rounded text-sm font-medium transition ${X==="installed"?"bg-[var(--color-surface-raised)] text-white":"text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]"}`,children:["Installed (",D.length,")"]},void 0,!0,void 0,this),z.jsxDEV("button",{onClick:()=>U("github"),className:`px-4 py-2 rounded text-sm font-medium transition ${X==="github"?"bg-[var(--color-surface-raised)] text-white":"text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]"}`,children:"Browse GitHub"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:()=>U("marketplace"),className:`px-4 py-2 rounded text-sm font-medium transition ${X==="marketplace"?"bg-[var(--color-surface-raised)] text-white":"text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]"}`,children:"Marketplace"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X==="installed"&&z.jsxDEV(z.Fragment,{children:y?z.jsxDEV("div",{className:"text-[var(--color-text-muted)]",children:"Loading skills..."},void 0,!1,void 0,this):B.length===0?z.jsxDEV("div",{className:"text-center py-20 text-[var(--color-text-muted)]",children:[z.jsxDEV("p",{className:"text-lg",children:"No skills installed"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm mt-1",children:"Create a skill or browse the marketplace"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:()=>U("marketplace"),className:"mt-4 bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] text-black px-4 py-2 rounded font-medium transition",children:"Browse Marketplace"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):D.length===0?z.jsxDEV("div",{className:"bg-[var(--color-surface)] card p-6 text-center",children:z.jsxDEV("p",{className:"text-[var(--color-text-muted)]",children:"No skills match this filter."},void 0,!1,void 0,this)},void 0,!1,void 0,this):z.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:D.map((J)=>{let O=_&&J.project_id?Z.find(($)=>$.id===J.project_id):null;return z.jsxDEV(Hz,{skill:J,project:O,onToggle:()=>_z(J.id),onDelete:()=>$z(J.id),onView:()=>T(J)},J.id,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),X==="github"&&z.jsxDEV("div",{className:"space-y-6",children:[z.jsxDEV("form",{onSubmit:(J)=>{J.preventDefault(),s()},className:"flex gap-2",children:[z.jsxDEV("input",{type:"text",value:a,onChange:(J)=>i(J.target.value),placeholder:"Enter GitHub repo (e.g., WordPress/agent-skills)",className:"flex-1 bg-[var(--color-surface)] border border-[var(--color-border-light)] rounded-lg px-4 py-3 focus:outline-none focus:border-[var(--color-accent)]"},void 0,!1,void 0,this),z.jsxDEV("button",{type:"submit",disabled:I,className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-black px-6 py-3 rounded-lg font-medium transition",children:I?"...":"Browse"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_&&R.length>0&&z.jsxDEV("div",{className:"flex items-center gap-3 p-3 bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded-lg",children:[z.jsxDEV("span",{className:"text-sm text-[var(--color-text-muted)]",children:"Install to:"},void 0,!1,void 0,this),z.jsxDEV(j,{value:x||"",onChange:(J)=>Zz(J||null),options:[{value:"",label:"Global (all projects)"},...Z.map((J)=>({value:J.id,label:J.name}))],placeholder:"Select scope..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V&&z.jsxDEV("div",{className:"text-red-400 text-sm p-3 bg-red-500/10 border border-red-500/20 rounded-lg",children:V},void 0,!1,void 0,this),q&&R.length>0&&z.jsxDEV("div",{className:"flex items-center justify-between",children:[z.jsxDEV("div",{className:"flex items-center gap-3",children:[z.jsxDEV("a",{href:q.url,target:"_blank",rel:"noopener noreferrer",className:"text-[var(--color-accent)] hover:underline font-medium",children:[q.owner,"/",q.repo]},void 0,!0,void 0,this),z.jsxDEV("span",{className:"text-sm text-[var(--color-text-muted)]",children:[R.length," skill",R.length!==1?"s":""," found"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),R.some((J)=>!g(J.name))&&z.jsxDEV("button",{onClick:Uz,disabled:!!e,className:"text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] hover:border-[var(--color-accent)] px-4 py-2 rounded transition disabled:opacity-50",children:"Install All"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I&&z.jsxDEV("div",{className:"text-center py-8 text-[var(--color-text-muted)]",children:"Fetching skills from repository..."},void 0,!1,void 0,this),!I&&!q&&!V&&z.jsxDEV("div",{className:"bg-[var(--color-surface)] card p-8 text-center",children:[z.jsxDEV("div",{className:"text-4xl mb-4",children:"\uD83D\uDCE6"},void 0,!1,void 0,this),z.jsxDEV("h3",{className:"text-lg font-medium mb-2",children:"Browse Skills from GitHub"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-[var(--color-text-muted)] mb-6 max-w-md mx-auto",children:"Enter a GitHub repository to browse and install skills. Skills are markdown files with instructions that teach agents how to perform specific tasks."},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex flex-wrap gap-2 justify-center",children:[{label:"WordPress Skills",repo:"WordPress/agent-skills"}].map(({label:J,repo:O})=>z.jsxDEV("button",{onClick:()=>{i(O),s(O)},className:"text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] hover:border-[var(--color-accent)] px-3 py-1.5 rounded transition",children:J},O,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),!I&&q&&R.length===0&&z.jsxDEV("div",{className:"text-center py-8 text-[var(--color-text-muted)]",children:"No skills found in this repository. Skills should be in subdirectories with a SKILL.md file."},void 0,!1,void 0,this),R.length>0&&z.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2",children:R.map((J)=>{let O=g(J.name),$=e===J.name;return z.jsxDEV("div",{className:`bg-[var(--color-surface)] border rounded-lg p-4 transition ${O?"border-green-500/30":"border-[var(--color-border)] hover:border-[var(--color-border-light)]"}`,children:z.jsxDEV("div",{className:"flex items-start justify-between gap-3",children:[z.jsxDEV("div",{className:"flex-1 min-w-0",children:[z.jsxDEV("div",{className:"flex items-center gap-2",children:[z.jsxDEV("h3",{className:"font-medium truncate",children:J.name},void 0,!1,void 0,this),O&&z.jsxDEV("span",{className:"text-xs text-green-400",children:"✓ Installed"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)] mt-1 line-clamp-2",children:J.description||"No description"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex items-center gap-2 mt-2 text-xs text-[var(--color-text-faint)]",children:[z.jsxDEV("span",{children:[(J.size/1024).toFixed(1),"KB"]},void 0,!0,void 0,this),z.jsxDEV("span",{className:"px-1.5 py-0.5 rounded bg-blue-500/10 text-blue-400",children:"GitHub"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex-shrink-0",children:O?z.jsxDEV("span",{className:"text-xs text-[var(--color-text-faint)] px-3 py-1.5",children:"Added"},void 0,!1,void 0,this):z.jsxDEV("button",{onClick:()=>Nz(J),disabled:$,className:"text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] hover:border-[var(--color-accent)] px-3 py-1.5 rounded transition disabled:opacity-50",children:$?"Installing...":"Install"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},J.name,!1,void 0,this)})},void 0,!1,void 0,this),z.jsxDEV("div",{className:"p-4 bg-[var(--color-surface)] card text-sm text-[var(--color-text-muted)]",children:z.jsxDEV("p",{children:["Skills are sourced from GitHub repositories. Each skill should be in its own directory with a"," ",z.jsxDEV("code",{className:"text-[var(--color-text-secondary)] bg-[var(--color-bg)] px-1 rounded",children:"SKILL.md"},void 0,!1,void 0,this)," file containing instructions."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X==="marketplace"&&z.jsxDEV(z.Fragment,{children:[z.jsxDEV("div",{className:"mb-6",children:z.jsxDEV("div",{className:"flex gap-2",children:[z.jsxDEV("input",{type:"text",value:m,onChange:(J)=>p(J.target.value),onKeyDown:(J)=>J.key==="Enter"&&E(),placeholder:"Search skills...",className:"flex-1 bg-[var(--color-surface)] border border-[var(--color-border)] rounded px-4 py-2 focus:outline-none focus:border-[var(--color-accent)]"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:()=>E(),disabled:c,className:"bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] text-white px-4 py-2 rounded font-medium transition border border-[var(--color-border-light)]",children:c?"...":"Search"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),c?z.jsxDEV("div",{className:"text-[var(--color-text-muted)]",children:"Loading..."},void 0,!1,void 0,this):h.length===0?z.jsxDEV("div",{className:"text-center py-20 text-[var(--color-text-muted)]",children:[z.jsxDEV("p",{className:"text-lg",children:"No skills found"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm mt-1",children:"Try a different search term"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):z.jsxDEV("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:h.map((J)=>z.jsxDEV(qz,{skill:J,installed:g(J.name),installing:Yz===J.id,onInstall:()=>Bz(J)},J.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,!1,void 0,this),G&&z.jsxDEV(Az,{authFetch:K,onClose:()=>Q(!1),onCreated:()=>{Q(!1),F()},projects:_?Z:void 0,defaultProjectId:Y&&Y!=="unassigned"?Y:null},void 0,!1,void 0,this),C&&z.jsxDEV(yz,{authFetch:K,onClose:()=>H(!1),onImported:()=>{H(!1),F()}},void 0,!1,void 0,this),v&&z.jsxDEV(Mz,{skill:v,authFetch:K,onClose:()=>T(null),onUpdated:()=>{T(null),F()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Hz({skill:K,project:Z,onToggle:Y,onDelete:B,onView:N}){let y={local:"Local",skillsmp:"SkillsMP",github:"GitHub",import:"Imported"}[K.source],M=()=>{if(Z)return z.jsxDEV("span",{className:"text-xs px-1.5 py-0.5 rounded",style:{backgroundColor:`${Z.color}20`,color:Z.color},children:Z.name},void 0,!1,void 0,this);if(K.project_id===null)return z.jsxDEV("span",{className:"text-xs text-[var(--color-text-muted)] bg-[var(--color-surface-raised)] px-1.5 py-0.5 rounded",children:"Global"},void 0,!1,void 0,this);return null};return z.jsxDEV("div",{className:`bg-[var(--color-surface)] rounded-lg p-5 border transition cursor-pointer ${K.enabled?"border-[var(--color-border)]":"border-[var(--color-border)] opacity-60"} hover:border-[var(--color-border-light)]`,onClick:N,children:[z.jsxDEV("div",{className:"flex items-start justify-between mb-3",children:[z.jsxDEV("div",{className:"flex-1 min-w-0",children:[z.jsxDEV("div",{className:"flex items-center gap-2",children:[z.jsxDEV("h3",{className:"font-semibold text-lg truncate",children:K.name},void 0,!1,void 0,this),M()]},void 0,!0,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-muted)] flex items-center gap-2 mt-0.5",children:[z.jsxDEV("span",{className:`px-1.5 py-0.5 rounded text-[10px] ${K.source==="skillsmp"?"bg-purple-500/20 text-purple-400":K.source==="github"?"bg-blue-500/20 text-blue-400":"bg-[var(--color-surface-raised)] text-[var(--color-text-secondary)]"}`,children:y},void 0,!1,void 0,this),K.metadata?.version&&z.jsxDEV("span",{children:["v",K.metadata.version]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("button",{onClick:(X)=>{X.stopPropagation(),Y()},className:`w-10 h-5 rounded-full transition-colors relative ${K.enabled?"bg-[var(--color-accent)]":"bg-[var(--color-surface-raised)]"}`,children:z.jsxDEV("span",{className:`absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform ${K.enabled?"left-5":"left-0.5"}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-secondary)] line-clamp-2 mb-4",children:K.description},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex items-center justify-between",children:[z.jsxDEV("div",{className:"flex gap-1 flex-wrap",children:[K.allowed_tools.slice(0,2).map((X)=>z.jsxDEV("span",{className:"text-xs bg-[var(--color-surface-raised)] px-2 py-0.5 rounded text-[var(--color-text-muted)]",children:X},X,!1,void 0,this)),K.allowed_tools.length>2&&z.jsxDEV("span",{className:"text-xs text-[var(--color-text-muted)]",children:["+",K.allowed_tools.length-2]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("button",{onClick:(X)=>{X.stopPropagation(),B()},className:"text-red-400 hover:text-red-300 text-sm",children:"Delete"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function qz({skill:K,installed:Z,installing:Y,onInstall:B}){return z.jsxDEV("div",{className:"bg-[var(--color-surface)] rounded-lg p-5 border border-[var(--color-border)] hover:border-[var(--color-border-light)] transition",children:[z.jsxDEV("div",{className:"flex items-start justify-between mb-3",children:[z.jsxDEV("div",{className:"flex-1 min-w-0",children:[z.jsxDEV("h3",{className:"font-semibold text-lg truncate",children:K.name},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-muted)] mt-0.5",children:["by ",K.author," · v",K.version]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex items-center gap-1 text-yellow-500 text-sm",children:["★ ",K.rating.toFixed(1)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-secondary)] line-clamp-2 mb-4",children:K.description},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex items-center justify-between",children:[z.jsxDEV("div",{className:"flex gap-1 flex-wrap",children:K.tags.slice(0,3).map((N)=>z.jsxDEV("span",{className:"text-xs bg-[var(--color-surface-raised)] px-2 py-0.5 rounded text-[var(--color-text-muted)]",children:N},N,!1,void 0,this))},void 0,!1,void 0,this),Z?z.jsxDEV("span",{className:"text-green-400 text-sm",children:"✓ Installed"},void 0,!1,void 0,this):z.jsxDEV("button",{onClick:B,disabled:Y,className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-black px-3 py-1 rounded text-sm font-medium transition",children:Y?"Installing...":"Install"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"mt-3 text-xs text-[var(--color-text-faint)]",children:[K.downloads.toLocaleString()," downloads"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Az({authFetch:K,onClose:Z,onCreated:Y,projects:B,defaultProjectId:N}){let[y,M]=W.useState(""),[X,U]=W.useState(""),[G,Q]=W.useState(""),[C,H]=W.useState(N||null),[v,T]=W.useState(!1),[f,w]=W.useState(null),P=B&&B.length>0,d=async()=>{if(!y||!X||!G){w("All fields are required");return}T(!0),w(null);try{let _={name:y,description:X,content:G,source:"local"};if(C)_.project_id=C;let m=await K("/api/skills",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(_)}),p=await m.json();if(!m.ok){w(p.error||"Failed to create skill"),T(!1);return}Y()}catch(_){w("Failed to create skill"),T(!1)}};return z.jsxDEV("div",{className:"fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4",onClick:Z,children:z.jsxDEV("div",{className:"bg-[var(--color-surface)] card w-full max-w-2xl max-h-[90vh] overflow-auto",onClick:(_)=>_.stopPropagation(),children:[z.jsxDEV("div",{className:"p-6 border-b border-[var(--color-border)]",children:z.jsxDEV("h2",{className:"text-xl font-semibold",children:"Create Skill"},void 0,!1,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("div",{className:"p-6 space-y-4",children:[f&&z.jsxDEV("div",{className:"bg-red-500/10 border border-red-500/30 rounded p-3 text-red-400 text-sm",children:f},void 0,!1,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-secondary)] mb-1",children:"Name"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"text",value:y,onChange:(_)=>M(_.target.value.toLowerCase().replace(/[^a-z0-9-]/g,"-")),placeholder:"my-skill-name",className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 focus:outline-none focus:border-[var(--color-accent)]"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"Lowercase letters, numbers, and hyphens only"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-secondary)] mb-1",children:"Description"},void 0,!1,void 0,this),z.jsxDEV("input",{type:"text",value:X,onChange:(_)=>U(_.target.value),placeholder:"What this skill does and when to use it...",className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 focus:outline-none focus:border-[var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P&&z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-secondary)] mb-1",children:"Scope"},void 0,!1,void 0,this),z.jsxDEV(j,{value:C||"",onChange:(_)=>H(_||null),options:[{value:"",label:"Global (all projects)"},...B.map((_)=>({value:_.id,label:_.name}))],placeholder:"Select scope..."},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-xs text-[var(--color-text-faint)] mt-1",children:"Global skills are available to all agents. Project-scoped skills are only available to agents in that project."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{children:[z.jsxDEV("label",{className:"block text-sm text-[var(--color-text-secondary)] mb-1",children:"Instructions (Markdown)"},void 0,!1,void 0,this),z.jsxDEV("textarea",{value:G,onChange:(_)=>Q(_.target.value),placeholder:`# Skill Instructions
2
+
3
+ Write detailed instructions here...`,rows:12,className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 focus:outline-none focus:border-[var(--color-accent)] font-mono text-sm"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"p-6 border-t border-[var(--color-border)] flex justify-end gap-3",children:[z.jsxDEV("button",{onClick:Z,className:"px-4 py-2 text-[var(--color-text-secondary)] hover:text-white transition",children:"Cancel"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:d,disabled:v,className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition",children:v?"Creating...":"Create Skill"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function yz({authFetch:K,onClose:Z,onImported:Y}){let[B,N]=W.useState(""),[y,M]=W.useState(!1),[X,U]=W.useState(null);return z.jsxDEV("div",{className:"fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4",onClick:Z,children:z.jsxDEV("div",{className:"bg-[var(--color-surface)] card w-full max-w-2xl max-h-[90vh] overflow-auto",onClick:(Q)=>Q.stopPropagation(),children:[z.jsxDEV("div",{className:"p-6 border-b border-[var(--color-border)]",children:[z.jsxDEV("h2",{className:"text-xl font-semibold",children:"Import Skill"},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)] mt-1",children:"Paste the contents of a SKILL.md file"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"p-6 space-y-4",children:[X&&z.jsxDEV("div",{className:"bg-red-500/10 border border-red-500/30 rounded p-3 text-red-400 text-sm",children:X},void 0,!1,void 0,this),z.jsxDEV("textarea",{value:B,onChange:(Q)=>N(Q.target.value),placeholder:`---
4
+ name: skill-name
5
+ description: What this skill does...
6
+ ---
7
+
8
+ # Instructions
9
+
10
+ Your skill instructions here...`,rows:16,className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 focus:outline-none focus:border-[var(--color-accent)] font-mono text-sm"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"p-6 border-t border-[var(--color-border)] flex justify-end gap-3",children:[z.jsxDEV("button",{onClick:Z,className:"px-4 py-2 text-[var(--color-text-secondary)] hover:text-white transition",children:"Cancel"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:async()=>{if(!B.trim()){U("Paste SKILL.md content");return}M(!0),U(null);try{let Q=await K("/api/skills/import",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:B})}),C=await Q.json();if(!Q.ok){U(C.error||"Failed to import skill"),M(!1);return}Y()}catch(Q){U("Failed to import skill"),M(!1)}},disabled:y,className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition",children:y?"Importing...":"Import Skill"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Mz({skill:K,authFetch:Z,onClose:Y,onUpdated:B}){let[N,y]=W.useState(!1),[M,X]=W.useState(K.content),[U,G]=W.useState(!1),Q=async()=>{G(!0);try{await Z(`/api/skills/${K.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:M})}),B()}catch(H){console.error("Failed to save:",H)}G(!1)},C=async()=>{try{let v=await(await Z(`/api/skills/${K.id}/export`)).text(),T=new Blob([v],{type:"text/markdown"}),f=URL.createObjectURL(T),w=document.createElement("a");w.href=f,w.download=`${K.name}-SKILL.md`,w.click(),URL.revokeObjectURL(f)}catch(H){console.error("Failed to export:",H)}};return z.jsxDEV("div",{className:"fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4",onClick:Y,children:z.jsxDEV("div",{className:"bg-[var(--color-surface)] card w-full max-w-3xl max-h-[90vh] overflow-auto",onClick:(H)=>H.stopPropagation(),children:[z.jsxDEV("div",{className:"p-6 border-b border-[var(--color-border)] flex items-center justify-between",children:[z.jsxDEV("div",{children:[z.jsxDEV("h2",{className:"text-xl font-semibold",children:K.name},void 0,!1,void 0,this),z.jsxDEV("p",{className:"text-sm text-[var(--color-text-muted)] mt-0.5",children:K.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex gap-2",children:[z.jsxDEV("button",{onClick:C,className:"text-sm text-[var(--color-text-secondary)] hover:text-white transition px-3 py-1 rounded border border-[var(--color-border-light)]",children:"Export"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:()=>y(!N),className:"text-sm text-[var(--color-text-secondary)] hover:text-white transition px-3 py-1 rounded border border-[var(--color-border-light)]",children:N?"View":"Edit"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"p-6",children:N?z.jsxDEV("textarea",{value:M,onChange:(H)=>X(H.target.value),rows:20,className:"w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-3 py-2 focus:outline-none focus:border-[var(--color-accent)] font-mono text-sm"},void 0,!1,void 0,this):z.jsxDEV("pre",{className:"bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded p-4 font-mono text-sm overflow-auto max-h-[60vh] whitespace-pre-wrap",children:K.content},void 0,!1,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("div",{className:"p-6 border-t border-[var(--color-border)] flex justify-between",children:[z.jsxDEV("div",{className:"text-xs text-[var(--color-text-faint)]",children:K.source!=="local"&&K.source_url&&z.jsxDEV("a",{href:K.source_url,target:"_blank",rel:"noopener noreferrer",className:"text-[var(--color-accent)] hover:underline",children:"View source →"},void 0,!1,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex gap-3",children:[z.jsxDEV("button",{onClick:Y,className:"px-4 py-2 text-[var(--color-text-secondary)] hover:text-white transition",children:"Close"},void 0,!1,void 0,this),N&&z.jsxDEV("button",{onClick:Q,disabled:U,className:"bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition",children:U?"Saving...":"Save Changes"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}
11
+ export{Rz as L};
12
+
13
+ //# debugId=F89C130753CEA5A864756E2164756E21