@apteva/apteva-darwin-x64 0.4.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/apteva +0 -0
  2. package/dist/ActivityPage.41nbye4r.js +3 -0
  3. package/dist/ActivityPage.41nbye4r.js.map +9 -0
  4. package/dist/ApiDocsPage.4smnt8m3.js +4 -0
  5. package/dist/ApiDocsPage.4smnt8m3.js.map +10 -0
  6. package/dist/App.0sbax9et.js +4 -0
  7. package/dist/App.0sbax9et.js.map +10 -0
  8. package/dist/App.0ws427h8.js +4 -0
  9. package/dist/App.0ws427h8.js.map +10 -0
  10. package/dist/App.6q6bar8b.js +4 -0
  11. package/dist/App.6q6bar8b.js.map +10 -0
  12. package/dist/App.80301vdb.js +4 -0
  13. package/dist/App.80301vdb.js.map +10 -0
  14. package/dist/App.af2wg84v.js +267 -0
  15. package/dist/App.af2wg84v.js.map +35 -0
  16. package/dist/App.ca1rz1ph.js +4 -0
  17. package/dist/App.ca1rz1ph.js.map +14 -0
  18. package/dist/App.ensa6z0r.js +4 -0
  19. package/dist/App.ensa6z0r.js.map +10 -0
  20. package/dist/App.f8g7tych.js +13 -0
  21. package/dist/App.f8g7tych.js.map +10 -0
  22. package/dist/App.mvtqv6qc.js +20 -0
  23. package/dist/App.mvtqv6qc.js.map +14 -0
  24. package/dist/App.ncgc9cxy.js +4 -0
  25. package/dist/App.ncgc9cxy.js.map +10 -0
  26. package/dist/App.p02f4ret.js +1 -0
  27. package/dist/App.p0fb1pds.js +4 -0
  28. package/dist/App.p0fb1pds.js.map +10 -0
  29. package/dist/App.pmaq48sj.js +4 -0
  30. package/dist/App.pmaq48sj.js.map +10 -0
  31. package/dist/App.yv87t9m5.js +4 -0
  32. package/dist/App.yv87t9m5.js.map +10 -0
  33. package/dist/App.zjmfm8p6.js +4 -0
  34. package/dist/App.zjmfm8p6.js.map +10 -0
  35. package/dist/ConnectionsPage.anb3rv9a.js +3 -0
  36. package/dist/ConnectionsPage.anb3rv9a.js.map +9 -0
  37. package/dist/McpPage.y396h6fy.js +3 -0
  38. package/dist/McpPage.y396h6fy.js.map +9 -0
  39. package/dist/SettingsPage.p1hc60gk.js +3 -0
  40. package/dist/SettingsPage.p1hc60gk.js.map +9 -0
  41. package/dist/SkillsPage.yj3xdsay.js +3 -0
  42. package/dist/SkillsPage.yj3xdsay.js.map +9 -0
  43. package/dist/TasksPage.sjv0khtv.js +3 -0
  44. package/dist/TasksPage.sjv0khtv.js.map +9 -0
  45. package/dist/TelemetryPage.2qm4w16r.js +3 -0
  46. package/dist/TelemetryPage.2qm4w16r.js.map +9 -0
  47. package/dist/TestsPage.zzs4qfj8.js +3 -0
  48. package/dist/TestsPage.zzs4qfj8.js.map +9 -0
  49. package/dist/apteva-kit.css +1 -0
  50. package/dist/icon.png +0 -0
  51. package/dist/index.html +16 -0
  52. package/dist/styles.css +1 -0
  53. package/index.js +1 -0
  54. package/package.json +10 -0
package/apteva ADDED
Binary file
@@ -0,0 +1,3 @@
1
+ import{d as a}from"./App.6q6bar8b.js";import"./App.ncgc9cxy.js";import"./App.mvtqv6qc.js";export{a as ActivityPage};
2
+
3
+ //# debugId=A836402CCF3683F564756E2164756E21
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "A836402CCF3683F564756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,4 @@
1
+ import{S as y,V as E,W as D,ca as l}from"./App.mvtqv6qc.js";var M=y(E(),1);var z=y(D(),1),V={get:"#61affe",post:"#49cc90",put:"#fca130",delete:"#f93e3e",patch:"#50e3c2"};function c({method:I,path:A,parameters:F,requestBody:L,authFetch:T}){let[U,R]=M.useState({}),[G,O]=M.useState(""),[_,k]=M.useState(null),[w,q]=M.useState(!1),[B,f]=M.useState(null);M.useEffect(()=>{if(L?.content?.["application/json"]?.schema){let W=L.content["application/json"].schema;if(W.example)O(JSON.stringify(W.example,null,2));else if(W.properties){let $={};for(let[N,Q]of Object.entries(W.properties))if(Q.example!==void 0)$[N]=Q.example;else if(Q.type==="string")$[N]="";else if(Q.type==="number"||Q.type==="integer")$[N]=0;else if(Q.type==="boolean")$[N]=!1;else if(Q.type==="array")$[N]=[];else if(Q.type==="object")$[N]={};O(JSON.stringify($,null,2))}}},[L]);let C=async()=>{q(!0),f(null),k(null);try{let W=A,$=[];for(let Z of F||[]){let H=U[Z.name]||"";if(Z.in==="path")W=W.replace(`{${Z.name}}`,encodeURIComponent(H));else if(Z.in==="query"&&H)$.push(`${Z.name}=${encodeURIComponent(H)}`)}if($.length>0)W+=`?${$.join("&")}`;let N={method:I.toUpperCase()};if(G&&["post","put","patch"].includes(I))N.headers={"Content-Type":"application/json"},N.body=G;let Q=await T(`/api${W}`,N),X;if(Q.headers.get("content-type")?.includes("application/json"))X=await Q.json();else X=await Q.text();k({status:Q.status,data:X})}catch(W){f(W.message||"Request failed")}finally{q(!1)}},b=F?.filter((W)=>W.in==="path")||[],K=F?.filter((W)=>W.in==="query")||[],S=["post","put","patch"].includes(I)&&L;return z.jsxDEV("div",{style:{marginTop:16,padding:16,background:"#0a0a14",borderRadius:6,border:"1px solid #222"},children:[z.jsxDEV("h4",{style:{fontSize:13,color:"#f97316",marginBottom:12,fontWeight:600},children:"Try it out"},void 0,!1,void 0,this),b.length>0&&z.jsxDEV("div",{style:{marginBottom:12},children:[z.jsxDEV("div",{style:{fontSize:11,color:"#666",marginBottom:6},children:"Path Parameters"},void 0,!1,void 0,this),b.map((W)=>z.jsxDEV("div",{style:{marginBottom:8},children:[z.jsxDEV("label",{style:{fontSize:12,color:"#888",display:"block",marginBottom:4},children:[W.name," ",W.required&&z.jsxDEV("span",{style:{color:"#f66"},children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("input",{type:"text",value:U[W.name]||"",onChange:($)=>R({...U,[W.name]:$.target.value}),placeholder:W.schema?.type||"string",style:{width:"100%",padding:"8px 12px",background:"#111",border:"1px solid #333",borderRadius:4,color:"#fff",fontSize:13,fontFamily:"monospace"}},void 0,!1,void 0,this)]},W.name,!0,void 0,this))]},void 0,!0,void 0,this),K.length>0&&z.jsxDEV("div",{style:{marginBottom:12},children:[z.jsxDEV("div",{style:{fontSize:11,color:"#666",marginBottom:6},children:"Query Parameters"},void 0,!1,void 0,this),K.map((W)=>z.jsxDEV("div",{style:{marginBottom:8},children:[z.jsxDEV("label",{style:{fontSize:12,color:"#888",display:"block",marginBottom:4},children:[W.name," ",W.required&&z.jsxDEV("span",{style:{color:"#f66"},children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("input",{type:"text",value:U[W.name]||"",onChange:($)=>R({...U,[W.name]:$.target.value}),placeholder:W.schema?.type||"string",style:{width:"100%",padding:"8px 12px",background:"#111",border:"1px solid #333",borderRadius:4,color:"#fff",fontSize:13,fontFamily:"monospace"}},void 0,!1,void 0,this)]},W.name,!0,void 0,this))]},void 0,!0,void 0,this),S&&z.jsxDEV("div",{style:{marginBottom:12},children:[z.jsxDEV("div",{style:{fontSize:11,color:"#666",marginBottom:6},children:"Request Body (JSON)"},void 0,!1,void 0,this),z.jsxDEV("textarea",{value:G,onChange:(W)=>O(W.target.value),rows:6,style:{width:"100%",padding:"8px 12px",background:"#111",border:"1px solid #333",borderRadius:4,color:"#fff",fontSize:12,fontFamily:"monospace",resize:"vertical"}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("button",{onClick:C,disabled:w,style:{padding:"10px 20px",background:w?"#333":"#f97316",color:w?"#666":"#000",border:"none",borderRadius:4,cursor:w?"not-allowed":"pointer",fontSize:13,fontWeight:600},children:w?"Executing...":"Execute"},void 0,!1,void 0,this),B&&z.jsxDEV("div",{style:{marginTop:12,padding:12,background:"#2a1515",borderRadius:4,color:"#f66",fontSize:12},children:B},void 0,!1,void 0,this),_&&z.jsxDEV("div",{style:{marginTop:12},children:[z.jsxDEV("div",{style:{fontSize:11,color:"#666",marginBottom:6},children:["Response"," ",z.jsxDEV("span",{style:{color:_.status>=200&&_.status<300?"#49cc90":"#f66"},children:_.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("pre",{style:{padding:12,background:"#111",borderRadius:4,color:"#888",fontSize:11,fontFamily:"monospace",overflow:"auto",maxHeight:300,whiteSpace:"pre-wrap",wordBreak:"break-word"},children:typeof _.data==="string"?_.data:JSON.stringify(_.data,null,2)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function h(){let{authFetch:I}=l(),[A,F]=M.useState(null),[L,T]=M.useState(!0),[U,R]=M.useState(new Set),[G,O]=M.useState(null),[_,k]=M.useState(!1);M.useEffect(()=>{B()},[]);async function w(){if(!A)return;try{await navigator.clipboard.writeText(JSON.stringify(A,null,2)),k(!0),setTimeout(()=>k(!1),2000)}catch(N){console.error("Failed to copy:",N)}}function q(){if(!A)return;let N=new Blob([JSON.stringify(A,null,2)],{type:"application/json"}),Q=URL.createObjectURL(N),X=document.createElement("a");X.href=Q,X.download="apteva-openapi.json",X.click(),URL.revokeObjectURL(Q)}async function B(){try{let N=await I("/api/openapi");if(N.ok){let Q=await N.json();F(Q)}}catch(N){console.error("Failed to load OpenAPI spec:",N)}finally{T(!1)}}function f(N){R((Q)=>{let X=new Set(Q);if(X.has(N))X.delete(N);else X.add(N);return X})}function C(N,Q=0){if(!N)return"{}";if(Q>2)return"...";if(N.$ref)return N.$ref.split("/").pop()||"Object";if(N.type==="array")return`${C(N.items,Q+1)}[]`;if(N.type==="object"&&N.properties){let X=Object.entries(N.properties).slice(0,3).map(([Z,H])=>`${Z}: ${H.type||"any"}`).join(", "),Y=Object.keys(N.properties).length>3?", ...":"";return`{ ${X}${Y} }`}return N.type||"any"}if(L)return z.jsxDEV("div",{style:{padding:24},children:z.jsxDEV("p",{style:{color:"#888"},children:"Loading API documentation..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(!A)return z.jsxDEV("div",{style:{padding:24},children:z.jsxDEV("p",{style:{color:"#f66"},children:"Failed to load API documentation"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let b=A.tags||[],K=Object.entries(A.paths);function S(N){let Q=new Set;function X(Y){if(!Y)return;if(typeof Y==="object"){if(Y.$ref){let Z=Y.$ref.split("/").pop();if(Z)Q.add(Z)}for(let Z of Object.values(Y))X(Z)}}return X(N.requestBody),X(N.responses),Q}function W(){if(!G||!A.components?.schemas)return Object.keys(A.components?.schemas||{});let N=new Set;for(let[Q,X]of $)for(let[Y,Z]of Object.entries(X)){if(!["get","post","put","delete","patch"].includes(Y))continue;if(Z.tags?.includes(G))S(Z).forEach((g)=>N.add(g))}return Array.from(N)}let $=G?K.filter(([N,Q])=>Object.values(Q).some((X)=>X.tags?.includes(G))):K;return z.jsxDEV("div",{style:{padding:24,maxWidth:1000,height:"100%",overflowY:"auto"},children:[z.jsxDEV("div",{style:{marginBottom:24},children:[z.jsxDEV("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:8},children:[z.jsxDEV("h1",{style:{fontSize:24,fontWeight:600},children:A.info.title},void 0,!1,void 0,this),z.jsxDEV("div",{style:{display:"flex",gap:8},children:[z.jsxDEV("button",{onClick:w,style:{padding:"8px 16px",borderRadius:4,border:"1px solid #333",background:_?"#49cc90":"#1a1a2e",color:_?"#000":"#fff",cursor:"pointer",fontSize:12,fontFamily:"inherit"},children:_?"Copied!":"Copy JSON"},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:q,style:{padding:"8px 16px",borderRadius:4,border:"1px solid #333",background:"#1a1a2e",color:"#fff",cursor:"pointer",fontSize:12,fontFamily:"inherit"},children:"Download"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("p",{style:{color:"#888",marginBottom:8},children:A.info.description.split(`
2
+ `)[0]},void 0,!1,void 0,this),z.jsxDEV("p",{style:{color:"#666",fontSize:12},children:["Version: ",A.info.version]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{style:{background:"#1a1a2e",padding:12,borderRadius:6,marginBottom:24,fontFamily:"monospace"},children:[z.jsxDEV("span",{style:{color:"#888"},children:"Base URL: "},void 0,!1,void 0,this),z.jsxDEV("span",{style:{color:"#61affe"},children:[window.location.origin,"/api"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{style:{marginBottom:24,display:"flex",flexWrap:"wrap",gap:8},children:[z.jsxDEV("button",{onClick:()=>O(null),style:{padding:"6px 12px",borderRadius:4,border:"1px solid #333",background:G===null?"#333":"transparent",color:G===null?"#fff":"#888",cursor:"pointer",fontSize:12},children:"All"},void 0,!1,void 0,this),b.map((N)=>z.jsxDEV("button",{onClick:()=>O(N.name),style:{padding:"6px 12px",borderRadius:4,border:"1px solid #333",background:G===N.name?"#333":"transparent",color:G===N.name?"#fff":"#888",cursor:"pointer",fontSize:12},title:N.description,children:N.name},N.name,!1,void 0,this))]},void 0,!0,void 0,this),z.jsxDEV("div",{style:{display:"flex",flexDirection:"column",gap:8},children:$.map(([N,Q])=>Object.entries(Q).filter(([X])=>["get","post","put","delete","patch"].includes(X)).map(([X,Y])=>{let Z=`${X}:${N}`,H=U.has(Z),g=X.toUpperCase(),j=V[X]||"#888";return z.jsxDEV("div",{style:{border:"1px solid #333",borderRadius:6,overflow:"hidden"},children:[z.jsxDEV("div",{onClick:()=>f(Z),style:{display:"flex",alignItems:"center",gap:12,padding:"12px 16px",background:H?"#1a1a2e":"transparent",cursor:"pointer"},children:[z.jsxDEV("span",{style:{background:j,color:"#000",padding:"4px 8px",borderRadius:4,fontSize:11,fontWeight:600,minWidth:60,textAlign:"center"},children:g},void 0,!1,void 0,this),z.jsxDEV("span",{style:{fontFamily:"monospace",color:"#fff"},children:N},void 0,!1,void 0,this),z.jsxDEV("span",{style:{color:"#888",flex:1,fontSize:13},children:Y.summary},void 0,!1,void 0,this),z.jsxDEV("span",{style:{color:"#666",fontSize:12},children:H?"[-]":"[+]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H&&z.jsxDEV("div",{style:{padding:16,background:"#0d0d1a",borderTop:"1px solid #333"},children:[Y.description&&z.jsxDEV("p",{style:{color:"#888",marginBottom:16,fontSize:13},children:Y.description},void 0,!1,void 0,this),Y.parameters&&Y.parameters.length>0&&z.jsxDEV("div",{style:{marginBottom:16},children:[z.jsxDEV("h4",{style:{fontSize:13,color:"#888",marginBottom:8},children:"Parameters"},void 0,!1,void 0,this),z.jsxDEV("div",{style:{background:"#1a1a2e",borderRadius:4,padding:12},children:Y.parameters.map((J)=>z.jsxDEV("div",{style:{display:"flex",gap:12,marginBottom:8,fontSize:12},children:[z.jsxDEV("span",{style:{color:"#61affe",minWidth:100},children:[J.name,J.required&&z.jsxDEV("span",{style:{color:"#f66"},children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("span",{style:{color:"#666"},children:["(",J.in,")"]},void 0,!0,void 0,this),z.jsxDEV("span",{style:{color:"#888"},children:J.schema?.type||"string"},void 0,!1,void 0,this),J.description&&z.jsxDEV("span",{style:{color:"#666"},children:["- ",J.description]},void 0,!0,void 0,this)]},J.name,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y.requestBody&&z.jsxDEV("div",{style:{marginBottom:16},children:[z.jsxDEV("h4",{style:{fontSize:13,color:"#888",marginBottom:8},children:["Request Body",Y.requestBody.required&&z.jsxDEV("span",{style:{color:"#f66"},children:" (required)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{style:{background:"#1a1a2e",borderRadius:4,padding:12,fontFamily:"monospace",fontSize:12,color:"#49cc90"},children:Object.entries(Y.requestBody.content||{}).map(([J,P])=>z.jsxDEV("div",{children:[z.jsxDEV("span",{style:{color:"#666"},children:[J,": "]},void 0,!0,void 0,this),C(P.schema)]},J,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y.responses&&z.jsxDEV("div",{children:[z.jsxDEV("h4",{style:{fontSize:13,color:"#888",marginBottom:8},children:"Responses"},void 0,!1,void 0,this),z.jsxDEV("div",{style:{background:"#1a1a2e",borderRadius:4,padding:12},children:Object.entries(Y.responses).map(([J,P])=>{let v=P.content?.["application/json"]?.schema,u=v?.$ref?.split("/").pop(),n=v?.type,i=v?.items?.$ref?.split("/").pop();return z.jsxDEV("div",{style:{marginBottom:12,fontSize:12},children:[z.jsxDEV("div",{style:{display:"flex",gap:12,marginBottom:4},children:[z.jsxDEV("span",{style:{color:J.startsWith("2")?"#49cc90":"#f66",minWidth:40},children:J},void 0,!1,void 0,this),z.jsxDEV("span",{style:{color:"#888"},children:P.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v&&z.jsxDEV("div",{style:{marginLeft:52,padding:"8px 12px",background:"#0d0d1a",borderRadius:4,fontFamily:"monospace"},children:u?z.jsxDEV("span",{style:{color:"#61affe"},children:u},void 0,!1,void 0,this):n==="array"&&i?z.jsxDEV("span",{style:{color:"#61affe"},children:[i,"[]"]},void 0,!0,void 0,this):n==="array"?z.jsxDEV("span",{style:{color:"#888"},children:"array"},void 0,!1,void 0,this):z.jsxDEV("span",{style:{color:"#888"},children:C(v)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},J,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV(c,{method:X,path:N,parameters:Y.parameters,requestBody:Y.requestBody,authFetch:I},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},Z,!0,void 0,this)}))},void 0,!1,void 0,this),A.components?.schemas&&W().length>0&&z.jsxDEV("div",{style:{marginTop:32},children:[z.jsxDEV("h2",{style:{fontSize:18,fontWeight:600,marginBottom:16},children:["Schemas ",G&&z.jsxDEV("span",{style:{color:"#666",fontSize:14},children:["(",G,")"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{style:{display:"flex",flexDirection:"column",gap:8},children:W().map((N)=>{let Q=A.components.schemas[N];if(!Q)return null;return z.jsxDEV("div",{style:{border:"1px solid #333",borderRadius:6,padding:12},children:[z.jsxDEV("h3",{style:{fontSize:14,color:"#61affe",marginBottom:8},children:N},void 0,!1,void 0,this),Q.properties&&z.jsxDEV("div",{style:{fontSize:12},children:Object.entries(Q.properties).map(([X,Y])=>z.jsxDEV("div",{style:{display:"flex",gap:8,marginBottom:4,fontFamily:"monospace"},children:[z.jsxDEV("span",{style:{color:"#fff",minWidth:120},children:X},void 0,!1,void 0,this),z.jsxDEV("span",{style:{color:"#888"},children:[Y.type||(Y.$ref?Y.$ref.split("/").pop():"any"),Y.nullable&&" | null"]},void 0,!0,void 0,this),Y.enum&&z.jsxDEV("span",{style:{color:"#666"},children:["[",Y.enum.join(" | "),"]"]},void 0,!0,void 0,this)]},X,!0,void 0,this))},void 0,!1,void 0,this)]},N,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}export{h as ApiDocsPage};
3
+
4
+ //# debugId=F1BCC3A63EFF032E64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/api/ApiDocsPage.tsx"],
4
+ "sourcesContent": [
5
+ "import { useState, useEffect } from \"react\";\nimport { useAuth } from \"../../context\";\n\ninterface OpenApiPath {\n [method: string]: {\n tags?: string[];\n summary?: string;\n description?: string;\n parameters?: Array<{\n name: string;\n in: string;\n required?: boolean;\n schema?: { type: string };\n description?: string;\n }>;\n requestBody?: {\n required?: boolean;\n content?: {\n [mediaType: string]: {\n schema?: any;\n };\n };\n };\n responses?: {\n [code: string]: {\n description?: string;\n content?: any;\n };\n };\n };\n}\n\ninterface OpenApiSpec {\n info: {\n title: string;\n description: string;\n version: string;\n };\n tags?: Array<{ name: string; description: string }>;\n paths: { [path: string]: OpenApiPath };\n components?: {\n schemas?: { [name: string]: any };\n };\n}\n\nconst METHOD_COLORS: Record<string, string> = {\n get: \"#61affe\",\n post: \"#49cc90\",\n put: \"#fca130\",\n delete: \"#f93e3e\",\n patch: \"#50e3c2\",\n};\n\n// Try It Out component\nfunction TryItOut({\n method,\n path,\n parameters,\n requestBody,\n authFetch,\n}: {\n method: string;\n path: string;\n parameters?: Array<{\n name: string;\n in: string;\n required?: boolean;\n schema?: { type: string };\n }>;\n requestBody?: any;\n authFetch: (url: string, options?: RequestInit) => Promise<Response>;\n}) {\n const [paramValues, setParamValues] = useState<Record<string, string>>({});\n const [bodyValue, setBodyValue] = useState(\"\");\n const [response, setResponse] = useState<{ status: number; data: any } | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Initialize body with example if available\n useEffect(() => {\n if (requestBody?.content?.[\"application/json\"]?.schema) {\n const schema = requestBody.content[\"application/json\"].schema;\n if (schema.example) {\n setBodyValue(JSON.stringify(schema.example, null, 2));\n } else if (schema.properties) {\n // Generate example from properties\n const example: Record<string, any> = {};\n for (const [key, prop] of Object.entries(schema.properties) as [string, any][]) {\n if (prop.example !== undefined) {\n example[key] = prop.example;\n } else if (prop.type === \"string\") {\n example[key] = \"\";\n } else if (prop.type === \"number\" || prop.type === \"integer\") {\n example[key] = 0;\n } else if (prop.type === \"boolean\") {\n example[key] = false;\n } else if (prop.type === \"array\") {\n example[key] = [];\n } else if (prop.type === \"object\") {\n example[key] = {};\n }\n }\n setBodyValue(JSON.stringify(example, null, 2));\n }\n }\n }, [requestBody]);\n\n const execute = async () => {\n setLoading(true);\n setError(null);\n setResponse(null);\n\n try {\n // Build URL with path parameters\n let url = path;\n const queryParams: string[] = [];\n\n for (const param of parameters || []) {\n const value = paramValues[param.name] || \"\";\n if (param.in === \"path\") {\n url = url.replace(`{${param.name}}`, encodeURIComponent(value));\n } else if (param.in === \"query\" && value) {\n queryParams.push(`${param.name}=${encodeURIComponent(value)}`);\n }\n }\n\n if (queryParams.length > 0) {\n url += `?${queryParams.join(\"&\")}`;\n }\n\n const options: RequestInit = {\n method: method.toUpperCase(),\n };\n\n if (bodyValue && [\"post\", \"put\", \"patch\"].includes(method)) {\n options.headers = { \"Content-Type\": \"application/json\" };\n options.body = bodyValue;\n }\n\n const res = await authFetch(`/api${url}`, options);\n let data;\n const contentType = res.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n data = await res.json();\n } else {\n data = await res.text();\n }\n\n setResponse({ status: res.status, data });\n } catch (err: any) {\n setError(err.message || \"Request failed\");\n } finally {\n setLoading(false);\n }\n };\n\n const pathParams = parameters?.filter((p) => p.in === \"path\") || [];\n const queryParams = parameters?.filter((p) => p.in === \"query\") || [];\n const hasBody = [\"post\", \"put\", \"patch\"].includes(method) && requestBody;\n\n return (\n <div style={{ marginTop: 16, padding: 16, background: \"#0a0a14\", borderRadius: 6, border: \"1px solid #222\" }}>\n <h4 style={{ fontSize: 13, color: \"#f97316\", marginBottom: 12, fontWeight: 600 }}>Try it out</h4>\n\n {/* Path Parameters */}\n {pathParams.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontSize: 11, color: \"#666\", marginBottom: 6 }}>Path Parameters</div>\n {pathParams.map((param) => (\n <div key={param.name} style={{ marginBottom: 8 }}>\n <label style={{ fontSize: 12, color: \"#888\", display: \"block\", marginBottom: 4 }}>\n {param.name} {param.required && <span style={{ color: \"#f66\" }}>*</span>}\n </label>\n <input\n type=\"text\"\n value={paramValues[param.name] || \"\"}\n onChange={(e) => setParamValues({ ...paramValues, [param.name]: e.target.value })}\n placeholder={param.schema?.type || \"string\"}\n style={{\n width: \"100%\",\n padding: \"8px 12px\",\n background: \"#111\",\n border: \"1px solid #333\",\n borderRadius: 4,\n color: \"#fff\",\n fontSize: 13,\n fontFamily: \"monospace\",\n }}\n />\n </div>\n ))}\n </div>\n )}\n\n {/* Query Parameters */}\n {queryParams.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontSize: 11, color: \"#666\", marginBottom: 6 }}>Query Parameters</div>\n {queryParams.map((param) => (\n <div key={param.name} style={{ marginBottom: 8 }}>\n <label style={{ fontSize: 12, color: \"#888\", display: \"block\", marginBottom: 4 }}>\n {param.name} {param.required && <span style={{ color: \"#f66\" }}>*</span>}\n </label>\n <input\n type=\"text\"\n value={paramValues[param.name] || \"\"}\n onChange={(e) => setParamValues({ ...paramValues, [param.name]: e.target.value })}\n placeholder={param.schema?.type || \"string\"}\n style={{\n width: \"100%\",\n padding: \"8px 12px\",\n background: \"#111\",\n border: \"1px solid #333\",\n borderRadius: 4,\n color: \"#fff\",\n fontSize: 13,\n fontFamily: \"monospace\",\n }}\n />\n </div>\n ))}\n </div>\n )}\n\n {/* Request Body */}\n {hasBody && (\n <div style={{ marginBottom: 12 }}>\n <div style={{ fontSize: 11, color: \"#666\", marginBottom: 6 }}>Request Body (JSON)</div>\n <textarea\n value={bodyValue}\n onChange={(e) => setBodyValue(e.target.value)}\n rows={6}\n style={{\n width: \"100%\",\n padding: \"8px 12px\",\n background: \"#111\",\n border: \"1px solid #333\",\n borderRadius: 4,\n color: \"#fff\",\n fontSize: 12,\n fontFamily: \"monospace\",\n resize: \"vertical\",\n }}\n />\n </div>\n )}\n\n {/* Execute Button */}\n <button\n onClick={execute}\n disabled={loading}\n style={{\n padding: \"10px 20px\",\n background: loading ? \"#333\" : \"#f97316\",\n color: loading ? \"#666\" : \"#000\",\n border: \"none\",\n borderRadius: 4,\n cursor: loading ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n {loading ? \"Executing...\" : \"Execute\"}\n </button>\n\n {/* Error */}\n {error && (\n <div style={{ marginTop: 12, padding: 12, background: \"#2a1515\", borderRadius: 4, color: \"#f66\", fontSize: 12 }}>\n {error}\n </div>\n )}\n\n {/* Response */}\n {response && (\n <div style={{ marginTop: 12 }}>\n <div style={{ fontSize: 11, color: \"#666\", marginBottom: 6 }}>\n Response{\" \"}\n <span style={{ color: response.status >= 200 && response.status < 300 ? \"#49cc90\" : \"#f66\" }}>\n {response.status}\n </span>\n </div>\n <pre\n style={{\n padding: 12,\n background: \"#111\",\n borderRadius: 4,\n color: \"#888\",\n fontSize: 11,\n fontFamily: \"monospace\",\n overflow: \"auto\",\n maxHeight: 300,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {typeof response.data === \"string\" ? response.data : JSON.stringify(response.data, null, 2)}\n </pre>\n </div>\n )}\n </div>\n );\n}\n\nexport function ApiDocsPage() {\n const { authFetch } = useAuth();\n const [spec, setSpec] = useState<OpenApiSpec | null>(null);\n const [loading, setLoading] = useState(true);\n const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set());\n const [selectedTag, setSelectedTag] = useState<string | null>(null);\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n loadSpec();\n }, []);\n\n async function copyToClipboard() {\n if (!spec) return;\n try {\n await navigator.clipboard.writeText(JSON.stringify(spec, null, 2));\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"Failed to copy:\", err);\n }\n }\n\n function downloadJson() {\n if (!spec) return;\n const blob = new Blob([JSON.stringify(spec, null, 2)], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = \"apteva-openapi.json\";\n a.click();\n URL.revokeObjectURL(url);\n }\n\n async function loadSpec() {\n try {\n const res = await authFetch(\"/api/openapi\");\n if (res.ok) {\n const data = await res.json();\n setSpec(data);\n }\n } catch (err) {\n console.error(\"Failed to load OpenAPI spec:\", err);\n } finally {\n setLoading(false);\n }\n }\n\n function togglePath(pathKey: string) {\n setExpandedPaths((prev) => {\n const next = new Set(prev);\n if (next.has(pathKey)) {\n next.delete(pathKey);\n } else {\n next.add(pathKey);\n }\n return next;\n });\n }\n\n function getSchemaPreview(schema: any, depth = 0): string {\n if (!schema) return \"{}\";\n if (depth > 2) return \"...\";\n\n if (schema.$ref) {\n const refName = schema.$ref.split(\"/\").pop();\n return refName || \"Object\";\n }\n\n if (schema.type === \"array\") {\n const itemType = getSchemaPreview(schema.items, depth + 1);\n return `${itemType}[]`;\n }\n\n if (schema.type === \"object\" && schema.properties) {\n const props = Object.entries(schema.properties)\n .slice(0, 3)\n .map(([k, v]: [string, any]) => `${k}: ${v.type || \"any\"}`)\n .join(\", \");\n const more = Object.keys(schema.properties).length > 3 ? \", ...\" : \"\";\n return `{ ${props}${more} }`;\n }\n\n return schema.type || \"any\";\n }\n\n if (loading) {\n return (\n <div style={{ padding: 24 }}>\n <p style={{ color: \"#888\" }}>Loading API documentation...</p>\n </div>\n );\n }\n\n if (!spec) {\n return (\n <div style={{ padding: 24 }}>\n <p style={{ color: \"#f66\" }}>Failed to load API documentation</p>\n </div>\n );\n }\n\n const tags = spec.tags || [];\n const paths = Object.entries(spec.paths);\n\n // Extract schema names referenced by a method\n function getReferencedSchemas(method: any): Set<string> {\n const refs = new Set<string>();\n\n function extractRefs(obj: any) {\n if (!obj) return;\n if (typeof obj === \"object\") {\n if (obj.$ref) {\n const name = obj.$ref.split(\"/\").pop();\n if (name) refs.add(name);\n }\n for (const value of Object.values(obj)) {\n extractRefs(value);\n }\n }\n }\n\n extractRefs(method.requestBody);\n extractRefs(method.responses);\n return refs;\n }\n\n // Get all schemas referenced by filtered endpoints\n function getFilteredSchemas(): string[] {\n if (!selectedTag || !spec.components?.schemas) {\n return Object.keys(spec.components?.schemas || {});\n }\n\n const usedSchemas = new Set<string>();\n\n for (const [_, methods] of filteredPaths) {\n for (const [method, details] of Object.entries(methods)) {\n if (![\"get\", \"post\", \"put\", \"delete\", \"patch\"].includes(method)) continue;\n if (details.tags?.includes(selectedTag)) {\n const refs = getReferencedSchemas(details);\n refs.forEach(r => usedSchemas.add(r));\n }\n }\n }\n\n return Array.from(usedSchemas);\n }\n\n // Filter paths by selected tag\n const filteredPaths = selectedTag\n ? paths.filter(([_, methods]) =>\n Object.values(methods).some((m) => m.tags?.includes(selectedTag))\n )\n : paths;\n\n return (\n <div style={{ padding: 24, maxWidth: 1000, height: \"100%\", overflowY: \"auto\" }}>\n <div style={{ marginBottom: 24 }}>\n <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"flex-start\", marginBottom: 8 }}>\n <h1 style={{ fontSize: 24, fontWeight: 600 }}>\n {spec.info.title}\n </h1>\n <div style={{ display: \"flex\", gap: 8 }}>\n <button\n onClick={copyToClipboard}\n style={{\n padding: \"8px 16px\",\n borderRadius: 4,\n border: \"1px solid #333\",\n background: copied ? \"#49cc90\" : \"#1a1a2e\",\n color: copied ? \"#000\" : \"#fff\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n }}\n >\n {copied ? \"Copied!\" : \"Copy JSON\"}\n </button>\n <button\n onClick={downloadJson}\n style={{\n padding: \"8px 16px\",\n borderRadius: 4,\n border: \"1px solid #333\",\n background: \"#1a1a2e\",\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n }}\n >\n Download\n </button>\n </div>\n </div>\n <p style={{ color: \"#888\", marginBottom: 8 }}>\n {spec.info.description.split(\"\\n\")[0]}\n </p>\n <p style={{ color: \"#666\", fontSize: 12 }}>Version: {spec.info.version}</p>\n </div>\n\n {/* Base URL */}\n <div\n style={{\n background: \"#1a1a2e\",\n padding: 12,\n borderRadius: 6,\n marginBottom: 24,\n fontFamily: \"monospace\",\n }}\n >\n <span style={{ color: \"#888\" }}>Base URL: </span>\n <span style={{ color: \"#61affe\" }}>\n {window.location.origin}/api\n </span>\n </div>\n\n {/* Tag filters */}\n <div style={{ marginBottom: 24, display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n <button\n onClick={() => setSelectedTag(null)}\n style={{\n padding: \"6px 12px\",\n borderRadius: 4,\n border: \"1px solid #333\",\n background: selectedTag === null ? \"#333\" : \"transparent\",\n color: selectedTag === null ? \"#fff\" : \"#888\",\n cursor: \"pointer\",\n fontSize: 12,\n }}\n >\n All\n </button>\n {tags.map((tag) => (\n <button\n key={tag.name}\n onClick={() => setSelectedTag(tag.name)}\n style={{\n padding: \"6px 12px\",\n borderRadius: 4,\n border: \"1px solid #333\",\n background: selectedTag === tag.name ? \"#333\" : \"transparent\",\n color: selectedTag === tag.name ? \"#fff\" : \"#888\",\n cursor: \"pointer\",\n fontSize: 12,\n }}\n title={tag.description}\n >\n {tag.name}\n </button>\n ))}\n </div>\n\n {/* Endpoints */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {filteredPaths.map(([path, methods]) =>\n Object.entries(methods)\n .filter(([method]) => [\"get\", \"post\", \"put\", \"delete\", \"patch\"].includes(method))\n .map(([method, details]) => {\n const pathKey = `${method}:${path}`;\n const isExpanded = expandedPaths.has(pathKey);\n const methodUpper = method.toUpperCase();\n const color = METHOD_COLORS[method] || \"#888\";\n\n return (\n <div\n key={pathKey}\n style={{\n border: \"1px solid #333\",\n borderRadius: 6,\n overflow: \"hidden\",\n }}\n >\n {/* Header */}\n <div\n onClick={() => togglePath(pathKey)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"12px 16px\",\n background: isExpanded ? \"#1a1a2e\" : \"transparent\",\n cursor: \"pointer\",\n }}\n >\n <span\n style={{\n background: color,\n color: \"#000\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontSize: 11,\n fontWeight: 600,\n minWidth: 60,\n textAlign: \"center\",\n }}\n >\n {methodUpper}\n </span>\n <span style={{ fontFamily: \"monospace\", color: \"#fff\" }}>\n {path}\n </span>\n <span style={{ color: \"#888\", flex: 1, fontSize: 13 }}>\n {details.summary}\n </span>\n <span style={{ color: \"#666\", fontSize: 12 }}>\n {isExpanded ? \"[-]\" : \"[+]\"}\n </span>\n </div>\n\n {/* Expanded details */}\n {isExpanded && (\n <div\n style={{\n padding: 16,\n background: \"#0d0d1a\",\n borderTop: \"1px solid #333\",\n }}\n >\n {details.description && (\n <p style={{ color: \"#888\", marginBottom: 16, fontSize: 13 }}>\n {details.description}\n </p>\n )}\n\n {/* Parameters */}\n {details.parameters && details.parameters.length > 0 && (\n <div style={{ marginBottom: 16 }}>\n <h4 style={{ fontSize: 13, color: \"#888\", marginBottom: 8 }}>\n Parameters\n </h4>\n <div\n style={{\n background: \"#1a1a2e\",\n borderRadius: 4,\n padding: 12,\n }}\n >\n {details.parameters.map((param) => (\n <div\n key={param.name}\n style={{\n display: \"flex\",\n gap: 12,\n marginBottom: 8,\n fontSize: 12,\n }}\n >\n <span style={{ color: \"#61affe\", minWidth: 100 }}>\n {param.name}\n {param.required && (\n <span style={{ color: \"#f66\" }}>*</span>\n )}\n </span>\n <span style={{ color: \"#666\" }}>({param.in})</span>\n <span style={{ color: \"#888\" }}>\n {param.schema?.type || \"string\"}\n </span>\n {param.description && (\n <span style={{ color: \"#666\" }}>\n - {param.description}\n </span>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Request Body */}\n {details.requestBody && (\n <div style={{ marginBottom: 16 }}>\n <h4 style={{ fontSize: 13, color: \"#888\", marginBottom: 8 }}>\n Request Body\n {details.requestBody.required && (\n <span style={{ color: \"#f66\" }}> (required)</span>\n )}\n </h4>\n <div\n style={{\n background: \"#1a1a2e\",\n borderRadius: 4,\n padding: 12,\n fontFamily: \"monospace\",\n fontSize: 12,\n color: \"#49cc90\",\n }}\n >\n {Object.entries(details.requestBody.content || {}).map(\n ([mediaType, content]) => (\n <div key={mediaType}>\n <span style={{ color: \"#666\" }}>{mediaType}: </span>\n {getSchemaPreview(content.schema)}\n </div>\n )\n )}\n </div>\n </div>\n )}\n\n {/* Responses */}\n {details.responses && (\n <div>\n <h4 style={{ fontSize: 13, color: \"#888\", marginBottom: 8 }}>\n Responses\n </h4>\n <div\n style={{\n background: \"#1a1a2e\",\n borderRadius: 4,\n padding: 12,\n }}\n >\n {Object.entries(details.responses).map(([code, resp]) => {\n const respContent = resp.content?.[\"application/json\"]?.schema;\n const schemaRef = respContent?.$ref?.split(\"/\").pop();\n const schemaType = respContent?.type;\n const schemaItems = respContent?.items?.$ref?.split(\"/\").pop();\n\n return (\n <div\n key={code}\n style={{\n marginBottom: 12,\n fontSize: 12,\n }}\n >\n <div style={{ display: \"flex\", gap: 12, marginBottom: 4 }}>\n <span\n style={{\n color: code.startsWith(\"2\") ? \"#49cc90\" : \"#f66\",\n minWidth: 40,\n }}\n >\n {code}\n </span>\n <span style={{ color: \"#888\" }}>{resp.description}</span>\n </div>\n {respContent && (\n <div\n style={{\n marginLeft: 52,\n padding: \"8px 12px\",\n background: \"#0d0d1a\",\n borderRadius: 4,\n fontFamily: \"monospace\",\n }}\n >\n {schemaRef ? (\n <span style={{ color: \"#61affe\" }}>{schemaRef}</span>\n ) : schemaType === \"array\" && schemaItems ? (\n <span style={{ color: \"#61affe\" }}>{schemaItems}[]</span>\n ) : schemaType === \"array\" ? (\n <span style={{ color: \"#888\" }}>array</span>\n ) : (\n <span style={{ color: \"#888\" }}>{getSchemaPreview(respContent)}</span>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Try It Out */}\n <TryItOut\n method={method}\n path={path}\n parameters={details.parameters}\n requestBody={details.requestBody}\n authFetch={authFetch}\n />\n </div>\n )}\n </div>\n );\n })\n )}\n </div>\n\n {/* Schemas section */}\n {spec.components?.schemas && getFilteredSchemas().length > 0 && (\n <div style={{ marginTop: 32 }}>\n <h2 style={{ fontSize: 18, fontWeight: 600, marginBottom: 16 }}>\n Schemas {selectedTag && <span style={{ color: \"#666\", fontSize: 14 }}>({selectedTag})</span>}\n </h2>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {getFilteredSchemas().map((name) => {\n const schema = spec.components!.schemas![name];\n if (!schema) return null;\n return (\n <div\n key={name}\n style={{\n border: \"1px solid #333\",\n borderRadius: 6,\n padding: 12,\n }}\n >\n <h3 style={{ fontSize: 14, color: \"#61affe\", marginBottom: 8 }}>\n {name}\n </h3>\n {schema.properties && (\n <div style={{ fontSize: 12 }}>\n {Object.entries(schema.properties).map(([prop, propSchema]: [string, any]) => (\n <div\n key={prop}\n style={{\n display: \"flex\",\n gap: 8,\n marginBottom: 4,\n fontFamily: \"monospace\",\n }}\n >\n <span style={{ color: \"#fff\", minWidth: 120 }}>{prop}</span>\n <span style={{ color: \"#888\" }}>\n {propSchema.type || (propSchema.$ref ? propSchema.$ref.split(\"/\").pop() : \"any\")}\n {propSchema.nullable && \" | null\"}\n </span>\n {propSchema.enum && (\n <span style={{ color: \"#666\" }}>\n [{propSchema.enum.join(\" | \")}]\n </span>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "F1BCC3A63EFF032E64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{O as V}from"./App.yv87t9m5.js";import{R as D}from"./App.p0fb1pds.js";import{S as P,V as Kk,W as v,Z as i,ca as o,fa as d}from"./App.mvtqv6qc.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-[#222] text-[#666]"}`,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-[#666] 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-[#1a1a1a] hover:bg-[#222] text-[#e0e0e0] 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-[#f97316] hover:bg-[#fb923c] 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-[#666] 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-[#333] 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-[#666] mb-2",children:"No tests yet"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#555] 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-[#f97316] hover:bg-[#fb923c] 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-[#111] border border-[#1a1a1a] rounded-lg p-4",children:q.jsxDEV("div",{className:"flex items-start justify-between",children:[q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("div",{className:"flex items-center gap-2 mb-1",children:[q.jsxDEV("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-[#888] 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-[#888] mb-1.5 line-clamp-2",children:k.behavior},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-xs text-[#666] space-y-0.5",children:[q.jsxDEV("div",{children:["Agent:"," ",q.jsxDEV("span",{className:"text-[#888]",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-[#888]",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-[#888]",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-[#888]",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-[#666] hover:text-[#888] hover:bg-[#1a1a1a] 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-[#1a1a1a] hover:bg-[#222] text-[#e0e0e0] 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-[#666] hover:text-[#888] hover:bg-[#1a1a1a] 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-[#666] hover:text-red-400 hover:bg-[#1a1a1a] 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-[#888]",children:"Run History"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:()=>{I(null),f(null)},className:"text-xs text-[#666] hover:text-[#888]",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-[#666]",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-[#0d0d0d] border border-[#1a1a1a] 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-[#666]",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-[#888] font-mono",children:[k.score,"/10"]},void 0,!0,void 0,this),k.selected_agent_name&&q.jsxDEV("span",{className:"text-xs text-[#555]",children:["Agent: ",k.selected_agent_name]},void 0,!0,void 0,this),q.jsxDEV("span",{className:"text-xs text-[#555]",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-[#555]",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-[#666] mb-1",children:"Planner:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[#aaa] bg-[#0a0a0a] p-2 rounded",children:[k.selected_agent_name&&q.jsxDEV("span",{className:"text-[#f97316]",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-[#666] mb-1",children:"Generated Message:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[#aaa] bg-[#0a0a0a] 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-[#666] mb-1",children:"Judge:"},void 0,!1,void 0,this),q.jsxDEV("div",{className:"text-sm text-[#aaa] bg-[#0a0a0a] 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-[#0a0a0a] 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-[#666] mb-1",children:"Agent Response (Thread):"},void 0,!1,void 0,this),q.jsxDEV("pre",{className:"text-xs text-[#888] bg-[#0a0a0a] 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-[#111] border border-[#1a1a1a] rounded-lg 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-[#666] 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-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{children:[q.jsxDEV("label",{className:"block text-xs text-[#666] mb-1",children:"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-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316] resize-none"},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#555] 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-[#666] 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-[#555] 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-[#888] hover:text-[#e0e0e0] transition",children:"Cancel"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:e,disabled:!M||!b,className:"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] 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=395511E423F4574664756E2164756E21
@@ -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-[#222] text-[#666]\"}`}>\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-[#666] 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-[#1a1a1a] hover:bg-[#222] text-[#e0e0e0] 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-[#f97316] hover:bg-[#fb923c] 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-[#666] text-sm\">Loading...</div>\n ) : tests.length === 0 ? (\n <div className=\"text-center py-16\">\n <div className=\"text-[#333] 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-[#666] mb-2\">No tests yet</p>\n <p className=\"text-xs text-[#555] 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-[#f97316] hover:bg-[#fb923c] 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-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <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-[#888] font-mono\">{tc.last_run.score}/10</span>\n )}\n </>)\n }\n </div>\n {tc.behavior && (\n <p className=\"text-xs text-[#888] mb-1.5 line-clamp-2\">{tc.behavior}</p>\n )}\n <div className=\"text-xs text-[#666] space-y-0.5\">\n <div>\n Agent:{\" \"}\n <span className=\"text-[#888]\">\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-[#888]\">\"{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-[#888]\">\"{tc.input_message}\"</span>\n </div>\n )}\n {tc.last_run && (\n <div>\n Last run:{\" \"}\n <span className=\"text-[#888]\">\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-[#666] hover:text-[#888] hover:bg-[#1a1a1a] 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-[#1a1a1a] hover:bg-[#222] text-[#e0e0e0] 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-[#666] hover:text-[#888] hover:bg-[#1a1a1a] rounded transition\"\n >\n Edit\n </button>\n <button\n onClick={() => handleDelete(tc.id)}\n className=\"px-2 py-1 text-xs text-[#666] hover:text-red-400 hover:bg-[#1a1a1a] 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-[#888]\">Run History</h2>\n <button\n onClick={() => { setSelectedRuns(null); setExpandedRun(null); }}\n className=\"text-xs text-[#666] hover:text-[#888]\"\n >\n Close\n </button>\n </div>\n {selectedRuns.runs.length === 0 ? (\n <p className=\"text-sm text-[#666]\">No runs yet</p>\n ) : (\n <div className=\"space-y-2\">\n {selectedRuns.runs.map(run => (\n <div key={run.id} className=\"bg-[#0d0d0d] border border-[#1a1a1a] 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-[#666]\">\n {run.duration_ms ? `${(run.duration_ms / 1000).toFixed(1)}s` : \"---\"}\n </span>\n {run.score != null && (\n <span className=\"text-xs text-[#888] font-mono\">{run.score}/10</span>\n )}\n {run.selected_agent_name && (\n <span className=\"text-xs text-[#555]\">\n Agent: {run.selected_agent_name}\n </span>\n )}\n <span className=\"text-xs text-[#555]\">\n {new Date(run.created_at).toLocaleString()}\n </span>\n </div>\n <span className=\"text-xs text-[#555]\">{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-[#666] mb-1\">Planner:</div>\n <div className=\"text-sm text-[#aaa] bg-[#0a0a0a] p-2 rounded\">\n {run.selected_agent_name && <span className=\"text-[#f97316]\">{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-[#666] mb-1\">Generated Message:</div>\n <div className=\"text-sm text-[#aaa] bg-[#0a0a0a] p-2 rounded\">\"{run.generated_message}\"</div>\n </div>\n )}\n {run.judge_reasoning && (\n <div>\n <div className=\"text-xs text-[#666] mb-1\">Judge:</div>\n <div className=\"text-sm text-[#aaa] bg-[#0a0a0a] 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-[#0a0a0a] p-2 rounded\">{run.error}</div>\n </div>\n )}\n {run.agent_response && (\n <div>\n <div className=\"text-xs text-[#666] mb-1\">Agent Response (Thread):</div>\n <pre className=\"text-xs text-[#888] bg-[#0a0a0a] 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-[#111] border border-[#1a1a1a] rounded-lg 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-[#666] 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-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs text-[#666] mb-1\">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-[#0a0a0a] border border-[#222] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316] resize-none\"\n />\n <p className=\"text-xs text-[#555] 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-[#666] 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-[#555] 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-[#888] hover:text-[#e0e0e0] transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={!formName || !formBehavior}\n className=\"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] 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": "wKAAA,uBA2DO,CAAS,EAAS,EAAG,CAC1B,IAAQ,aAAc,EAAQ,GACtB,oBAAqB,EAAY,GACjC,UAAS,iBAAkB,EAAW,GAEvC,EAAO,GAAY,WAAqB,CAAC,CAAC,GAC1C,EAAQ,GAAa,WAAwB,CAAC,CAAC,GAC/C,EAAS,GAAc,WAAS,EAAI,GACpC,EAAU,GAAe,WAAS,EAAK,GACvC,EAAa,GAAkB,WAA0B,IAAI,GAC7D,EAAc,GAAmB,WAAsB,IAAI,GAAK,GAChE,EAAY,GAAiB,WAAS,EAAK,GAC3C,EAAc,GAAmB,WAAqD,IAAI,GAC1F,EAAa,GAAkB,WAAwB,IAAI,GAE3D,EAAY,GAAiB,WAA6D,CAAC,CAAC,GAG5F,EAAU,GAAe,WAAS,EAAE,GACpC,EAAc,GAAmB,WAAS,EAAE,GAC5C,EAAa,GAAkB,WAAS,EAAE,EAE3C,EAAkB,GAAoB,IAAqB,OAAS,IAAqB,aAC3F,EAAmB,KAGjB,EAAgB,EAClB,EAAO,OAAO,KAAK,EAAE,YAAc,CAAe,EAClD,GAGI,OAAQ,GAAe,EAAa,CAAE,SAAU,OAAQ,MAAO,EAAG,CAAC,EACrE,EAAqB,SAAoB,IAAI,GAAK,EAExD,YAAU,IAAM,CACd,QAAW,KAAO,EAAY,CAC5B,GAAI,EAAmB,QAAQ,IAAI,EAAI,EAAE,EAAG,SAC5C,EAAmB,QAAQ,IAAI,EAAI,EAAE,EAErC,IAAM,EAAa,EAAI,MAAM,aAC7B,GAAI,CAAC,EAAY,SAEjB,GAAI,EAAI,OAAS,eACf,EAAc,MAAS,IAAK,GAAO,GAAa,CAAE,MAAO,UAAW,CAAE,EAAE,EACxE,EAAgB,KAAQ,IAAI,IAAI,CAAI,EAAE,IAAI,CAAU,CAAC,EAChD,QAAI,EAAI,OAAS,gBACtB,EAAc,MAAS,IAAK,GAAO,GAAa,CAAE,MAAO,UAAW,CAAE,EAAE,EACnE,QAAI,EAAI,OAAS,iBAAkB,CACxC,IAAM,EAAY,EAAI,MAAM,WAC5B,EAAc,MAAS,IAAK,GAAO,GAAa,CAAE,MAAO,YAAa,OAAQ,CAAU,CAAE,EAAE,EACvF,QAAI,EAAI,OAAS,eACtB,EAAc,MAAS,IAAK,GAAO,GAAa,CAAE,MAAO,SAAU,CAAE,EAAE,EAClE,QAAI,EAAI,OAAS,iBACtB,EAAc,KAAQ,CACpB,IAAM,EAAO,IAAK,CAAK,EAEvB,OADA,OAAO,EAAK,GACL,EACR,EACD,EAAgB,KAAQ,CACtB,IAAM,EAAO,IAAI,IAAI,CAAI,EAEzB,OADA,EAAK,OAAO,CAAU,EACf,EACR,EAED,EAAW,EAIf,GAAI,EAAmB,QAAQ,KAAO,IACpC,EAAmB,QAAU,IAAI,IAAI,CAAC,GAAG,EAAmB,OAAO,EAAE,MAAM,IAAI,CAAC,GAEjF,CAAC,CAAU,CAAC,EAEf,IAAM,EAAa,SAAY,CAC7B,GAAI,CACF,IAAM,EAAS,EAAkB,eAAe,IAAoB,GAC9D,EAAM,MAAM,EAAU,aAAa,GAAQ,EACjD,GAAI,EAAI,GAAI,EAAS,MAAM,EAAI,KAAK,CAAC,EACrC,KAAM,EACR,EAAW,EAAK,GAGZ,EAAc,SAAY,CAC9B,GAAI,CACF,IAAM,EAAM,MAAM,EAAU,aAAa,EACzC,GAAI,EAAI,GAAI,CACV,IAAM,EAAO,MAAM,EAAI,KAAK,EAC5B,GAAW,EAAK,QAAU,GAAM,IAAI,CAAC,KAAY,CAC/C,GAAI,EAAE,GACN,KAAM,EAAE,KACR,OAAQ,EAAE,OACV,SAAU,EAAE,SACZ,MAAO,EAAE,MACT,UAAW,EAAE,WAAa,IAC5B,EAAE,CAAC,GAEL,KAAM,IAGV,YAAU,IAAM,CACd,QAAQ,IAAI,CAAC,EAAW,EAAG,EAAY,CAAC,CAAC,GACxC,CAAC,CAAgB,CAAC,EAErB,IAAM,EAAa,IAAM,CACvB,EAAe,IAAI,EACnB,EAAY,EAAE,EACd,EAAgB,EAAE,EAClB,EAAe,EAAE,EACjB,EAAY,EAAI,GAGZ,EAAW,CAAC,IAAiB,CACjC,EAAe,CAAE,EACjB,EAAY,EAAG,IAAI,EACnB,EAAgB,EAAG,UAAY,EAAE,EACjC,EAAe,EAAG,UAAY,EAAE,EAChC,EAAY,EAAI,GAGZ,EAAa,SAAY,CAC7B,GAAI,CAAC,GAAY,CAAC,EAAc,OAEhC,IAAM,EAAY,CAChB,KAAM,EACN,SAAU,EACV,SAAU,GAAe,KACzB,WAAY,GAAmB,MACjC,EAEA,GAAI,EACF,MAAM,EAAU,cAAc,EAAY,KAAM,CAC9C,OAAQ,MACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAI,CAC3B,CAAC,EAED,WAAM,EAAU,aAAc,CAC5B,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAI,CAC3B,CAAC,EAGH,EAAY,EAAK,EACjB,EAAW,GAGP,GAAe,MAAO,IAAe,CAEzC,GAAI,CADO,MAAM,EAAQ,0DAA0D,EAC1E,OACT,MAAM,EAAU,cAAc,IAAM,CAAE,OAAQ,QAAS,CAAC,EACxD,EAAW,GAGP,GAAY,MAAO,IAAe,CACtC,EAAgB,KAAQ,IAAI,IAAI,CAAI,EAAE,IAAI,CAAE,CAAC,EAC7C,GAAI,CACF,MAAM,EAAU,cAAc,QAAU,CAAE,OAAQ,MAAO,CAAC,EAE1D,MAAM,EAAW,EACjB,KAAM,EAER,EAAgB,KAAQ,CACtB,IAAM,EAAO,IAAI,IAAI,CAAI,EAEzB,OADA,EAAK,OAAO,CAAE,EACP,EACR,EACD,EAAc,KAAQ,CACpB,IAAM,EAAO,IAAK,CAAK,EAEvB,OADA,OAAO,EAAK,GACL,EACR,GAGG,GAAe,SAAY,CAC/B,EAAc,EAAI,EAClB,GAAI,CACF,IAAM,EAAM,EAAM,IAAI,KAAK,EAAE,EAAE,EAC/B,EAAgB,IAAI,IAAI,CAAG,CAAC,EAC5B,MAAM,EAAU,iBAAkB,CAChC,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,cAAe,CAAI,CAAC,CAC7C,CAAC,EACD,MAAM,EAAW,EACjB,KAAM,EACR,EAAgB,IAAI,GAAK,EACzB,EAAc,EAAK,GAGf,GAAW,MAAO,IAAmB,CACzC,GAAI,CACF,IAAM,EAAM,MAAM,EAAU,cAAc,QAAa,EACvD,GAAI,EAAI,GACN,EAAgB,CAAE,SAAQ,KAAM,MAAM,EAAI,KAAK,CAAE,CAAC,EAEpD,KAAM,IAGJ,EAAgE,CACpE,SAAU,CAAE,MAAO,WAAY,MAAO,iDAAkD,EACxF,SAAU,CAAE,MAAO,WAAY,MAAO,uDAAwD,EAC9F,UAAW,CAAE,MAAO,YAAa,MAAO,iDAAkD,EAC1F,QAAS,CAAE,MAAO,UAAW,MAAO,oDAAqD,CAC3F,EAEM,EAAc,CAAC,IAAmB,CAOtC,OACE,SAEE,OAFF,CAAM,UAAW,2CAPoB,CACrC,OAAQ,iCACR,OAAQ,6BACR,MAAO,mCACP,QAAS,8BACX,EAEqE,IAAW,0BAA9E,SACG,EAAO,YAAY,GADtB,qBAEE,GAIA,GAAY,CAAC,IAAuB,CACxC,IAAM,EAAO,EAAW,GACxB,GAAI,CAAC,EAAM,OAAO,KAClB,IAAM,EAAQ,EAAY,EAAK,QAAU,EAAY,SACrD,OACE,SAGE,OAHF,CAAM,UAAW,mFAAmF,EAAM,sBAA1G,SAGE,CAFA,SAAC,OAAD,CAAM,UAAU,uCAAhB,qBAAsD,EACrD,EAAM,MAAO,EAAK,OAAS,MAAW,EAAK,SAAW,KAFzD,qBAGE,GAIN,OACE,SA4RE,MA5RF,CAAK,UAAU,2BAAf,SA4RE,CA3RC,EAGD,SAwBE,MAxBF,CAAK,UAAU,yCAAf,SAwBE,CAvBA,SAKE,MALF,UAKE,CAJA,SAAyC,KAAzC,CAAI,UAAU,oBAAd,uCAAyC,EACzC,SAEE,IAFF,CAAG,UAAU,2BAAb,wEAEE,IAJJ,qBAKE,EACF,SAgBE,MAhBF,CAAK,UAAU,aAAf,SAgBE,CAfC,EAAM,OAAS,GACd,SAME,SANF,CACE,QAAS,GACT,SAAU,EACV,UAAU,mHAHZ,SAKG,EAAa,aAAe,WAL/B,qBAME,EAEJ,SAKE,SALF,CACE,QAAS,EACT,UAAU,8FAFZ,4CAKE,IAfJ,qBAgBE,IAvBJ,qBAwBE,EAGD,EACC,SAAiD,MAAjD,CAAK,UAAU,sBAAf,4CAAiD,EAC/C,EAAM,SAAW,EACnB,SAcE,MAdF,CAAK,UAAU,oBAAf,SAcE,CAbA,SAIE,MAJF,CAAK,UAAU,4BAAf,SACE,SAEE,MAFF,CAAK,UAAU,oBAAoB,KAAK,OAAO,OAAO,eAAe,QAAQ,YAA7E,SACE,SAAC,OAAD,CAAM,cAAc,QAAQ,eAAe,QAAQ,YAAa,IAAK,EAAE,gJAAvE,qBAAsN,GADxN,qBAEE,GAHJ,qBAIE,EACF,SAA8C,IAA9C,CAAG,UAAU,mBAAb,8CAA8C,EAC9C,SAAkG,IAAlG,CAAG,UAAU,2BAAb,0FAAkG,EAClG,SAKE,SALF,CACE,QAAS,EACT,UAAU,8FAFZ,wDAKE,IAbJ,qBAcE,EAEF,SAiFE,MAjFF,CAAK,UAAU,YAAf,SACG,EAAM,IAAI,KACT,SA6EE,MA7EF,CAAiB,UAAU,mDAA3B,SACE,SA2EE,MA3EF,CAAK,UAAU,mCAAf,SA2EE,CA1EA,SA6CE,MA7CF,CAAK,UAAU,iBAAf,SA6CE,CA5CA,SAWE,MAXF,CAAK,UAAU,+BAAf,SAWE,CAVA,SAAiD,OAAjD,CAAM,UAAU,sBAAhB,SAAuC,EAAG,MAA1C,qBAAiD,EAChD,EAAW,EAAG,IACX,GAAU,EAAG,EAAE,EACf,EAAG,UAAa,8BAKd,CAJC,EAAY,EAAG,SAAS,MAAM,EAC9B,EAAG,SAAS,OAAS,MACpB,SAAwE,OAAxE,CAAM,UAAU,gCAAhB,SAAwE,CAAvB,EAAG,SAAS,MAA7D,6BAAwE,IAH5D,qBAKd,IATR,qBAWE,EACD,EAAG,UACF,SAAsE,IAAtE,CAAG,UAAU,0CAAb,SAAwD,EAAG,UAA3D,qBAAsE,EAExE,SA4BE,MA5BF,CAAK,UAAU,kCAAf,SA4BE,CA3BA,SAOE,MAPF,UAOE,CAPF,SACS,IACP,SAIE,OAJF,CAAM,UAAU,cAAhB,SACG,EAAG,aAAe,EAAG,UAAU,oBAC5B,GAAG,EAAG,SAAS,sCACf,oBAHN,qBAIE,IANJ,qBAOE,EACD,EAAG,UAAU,mBACZ,SAEE,MAFF,CAAK,UAAU,WAAf,SAEE,CAFF,YACW,SAAiE,OAAjE,CAAM,UAAU,cAAhB,SAAiE,CAAjE,IAAgC,EAAG,SAAS,kBAA5C,2BAAiE,IAD5E,qBAEE,EAEH,EAAG,eAAiB,CAAC,EAAG,UAAU,mBACjC,SAEE,MAFF,CAAK,UAAU,WAAf,SAEE,CAFF,YACW,SAAoD,OAApD,CAAM,UAAU,cAAhB,SAAoD,CAApD,IAAgC,EAAG,cAAnC,2BAAoD,IAD/D,qBAEE,EAEH,EAAG,UACF,SAME,MANF,UAME,CANF,YACY,IACV,SAGE,OAHF,CAAM,UAAU,cAAhB,SAGE,CAFC,EAAG,SAAS,YAAc,IAAI,EAAG,SAAS,YAAc,MAAM,QAAQ,CAAC,KAAO,MAC9E,EAAG,SAAS,iBAAmB,SAAS,EAAG,SAAS,gBAAgB,MAAM,EAAG,EAAE,IAAI,EAAG,SAAS,gBAAgB,OAAS,GAAK,MAAQ,QAFxI,qBAGE,IALJ,qBAME,IA1BN,qBA4BE,IA5CJ,qBA6CE,EACF,SA2BE,MA3BF,CAAK,UAAU,wCAAf,SA2BE,CA1BA,SAME,SANF,CACE,QAAS,IAAM,GAAS,EAAG,EAAE,EAC7B,UAAU,wFACV,MAAM,mBAHR,yCAME,EACF,SAME,SANF,CACE,QAAS,IAAM,GAAU,EAAG,EAAE,EAC9B,SAAU,EAAa,IAAI,EAAG,EAAE,EAChC,UAAU,uGAHZ,SAKG,EAAa,IAAI,EAAG,EAAE,EAAI,aAAe,OAL5C,qBAME,EACF,SAKE,SALF,CACE,QAAS,IAAM,EAAS,CAAE,EAC1B,UAAU,wFAFZ,sCAKE,EACF,SAKE,SALF,CACE,QAAS,IAAM,GAAa,EAAG,EAAE,EACjC,UAAU,yFAFZ,wCAKE,IA1BJ,qBA2BE,IA1EJ,qBA2EE,GA5EM,EAAG,GAAb,cA6EE,CACH,GAhFH,qBAiFE,EAIH,GACC,SAmFE,MAnFF,CAAK,UAAU,OAAf,SAmFE,CAlFA,SAQE,MARF,CAAK,UAAU,yCAAf,SAQE,CAPA,SAA2D,KAA3D,CAAI,UAAU,gCAAd,6CAA2D,EAC3D,SAKE,SALF,CACE,QAAS,IAAM,CAAE,EAAgB,IAAI,EAAG,EAAe,IAAI,GAC3D,UAAU,wCAFZ,uCAKE,IAPJ,qBAQE,EACD,EAAa,KAAK,SAAW,EAC5B,SAAgD,IAAhD,CAAG,UAAU,sBAAb,6CAAgD,EAEhD,SAoEE,MApEF,CAAK,UAAU,YAAf,SACG,EAAa,KAAK,IAAI,KACrB,SAgEE,MAhEF,CAAkB,UAAU,mDAA5B,SAgEE,CA/DA,SAsBE,MAtBF,CACE,UAAU,mDACV,QAAS,IAAM,EAAe,IAAgB,EAAI,GAAK,KAAO,EAAI,EAAE,EAFtE,SAsBE,CAlBA,SAgBE,MAhBF,CAAK,UAAU,0BAAf,SAgBE,CAfC,EAAY,EAAI,MAAM,EACvB,SAEE,OAFF,CAAM,UAAU,sBAAhB,SACG,EAAI,YAAc,IAAI,EAAI,YAAc,MAAM,QAAQ,CAAC,KAAO,OADjE,qBAEE,EACD,EAAI,OAAS,MACZ,SAAgE,OAAhE,CAAM,UAAU,gCAAhB,SAAgE,CAAf,EAAI,MAArD,6BAAgE,EAEjE,EAAI,qBACH,SAEE,OAFF,CAAM,UAAU,sBAAhB,SAEE,CAFF,UACU,EAAI,sBADd,qBAEE,EAEJ,SAEE,OAFF,CAAM,UAAU,sBAAhB,SACG,IAAI,KAAK,EAAI,UAAU,EAAE,eAAe,GAD3C,qBAEE,IAfJ,qBAgBE,EACF,SAA8E,OAA9E,CAAM,UAAU,sBAAhB,SAAuC,IAAgB,EAAI,GAAK,MAAQ,KAAxE,qBAA8E,IArBhF,qBAsBE,EACD,IAAgB,EAAI,IACnB,SAqCE,MArCF,CAAK,UAAU,iBAAf,SAqCE,CApCC,EAAI,mBACH,SAOE,MAPF,UAOE,CANA,SAAoD,MAApD,CAAK,UAAU,2BAAf,0CAAoD,EACpD,SAIE,MAJF,CAAK,UAAU,+CAAf,SAIE,CAHC,EAAI,qBAAuB,SAA4D,OAA5D,CAAM,UAAU,iBAAhB,SAAkC,EAAI,qBAAtC,qBAA4D,EACvF,EAAI,qBAAuB,QAC3B,EAAI,oBAHP,qBAIE,IANJ,qBAOE,EAEH,EAAI,mBACH,SAGE,MAHF,UAGE,CAFA,SAA8D,MAA9D,CAAK,UAAU,2BAAf,oDAA8D,EAC9D,SAAyF,MAAzF,CAAK,UAAU,+CAAf,SAAyF,CAAzF,IAAgE,EAAI,kBAApE,2BAAyF,IAF3F,qBAGE,EAEH,EAAI,iBACH,SAGE,MAHF,UAGE,CAFA,SAAkD,MAAlD,CAAK,UAAU,2BAAf,wCAAkD,EAClD,SAAqF,MAArF,CAAK,UAAU,+CAAf,SAA+D,EAAI,iBAAnE,qBAAqF,IAFvF,qBAGE,EAEH,EAAI,OACH,SAGE,MAHF,UAGE,CAFA,SAAmD,MAAnD,CAAK,UAAU,4BAAf,wCAAmD,EACnD,SAA4E,MAA5E,CAAK,UAAU,gDAAf,SAAgE,EAAI,OAApE,qBAA4E,IAF9E,qBAGE,EAEH,EAAI,gBACH,SAKE,MALF,UAKE,CAJA,SAAoE,MAApE,CAAK,UAAU,2BAAf,0DAAoE,EACpE,SAEE,MAFF,CAAK,UAAU,sEAAf,SACG,EAAI,gBADP,qBAEE,IAJJ,qBAKE,IAnCN,qBAqCE,IA9DI,EAAI,GAAd,cAgEE,CACH,GAnEH,qBAoEE,IAjFN,qBAmFE,EAIH,GACC,SA0DE,MA1DF,CAAK,UAAU,kEAAkE,QAAS,IAAM,EAAY,EAAK,EAAjH,SACE,SAwDE,MAxDF,CAAK,UAAU,wEAAwE,QAAS,KAAK,EAAE,gBAAgB,EAAvH,SAwDE,CAvDA,SAAiF,KAAjF,CAAI,UAAU,yBAAd,SAAwC,EAAc,YAAc,YAApE,qBAAiF,EAEjF,SAoCE,MApCF,CAAK,UAAU,YAAf,SAoCE,CAnCA,SAQE,MARF,UAQE,CAPA,SAAwD,QAAxD,CAAO,UAAU,iCAAjB,sCAAwD,EACxD,SAAC,QAAD,CACE,MAAO,EACP,SAAU,KAAK,EAAY,EAAE,OAAO,KAAK,EACzC,YAAY,4BACZ,UAAU,gHAJZ,qBAKA,IAPF,qBAQE,EAEF,SAUE,MAVF,UAUE,CATA,SAA4D,QAA5D,CAAO,UAAU,iCAAjB,0CAA4D,EAC5D,SAAC,WAAD,CACE,MAAO,EACP,SAAU,KAAK,EAAgB,EAAE,OAAO,KAAK,EAC7C,YAAY,+JACZ,KAAM,EACN,UAAU,4HALZ,qBAMA,EACA,SAA8G,IAA9G,CAAG,UAAU,2BAAb,sGAA8G,IAThH,qBAUE,EAEF,SAYE,MAZF,UAYE,CAXA,SAAyD,QAAzD,CAAO,UAAU,iCAAjB,uCAAyD,EACzD,SAAC,EAAD,CACE,MAAO,EACP,SAAU,EACV,YAAY,iCACZ,QAAS,EAAc,IAAI,MAAM,CAC/B,MAAO,EAAE,GACT,MAAO,GAAG,EAAE,SAAS,EAAE,SACzB,EAAE,GAPJ,qBAQA,EACA,SAAsF,IAAtF,CAAG,UAAU,2BAAb,8EAAsF,IAXxF,qBAYE,IAnCJ,qBAoCE,EAEF,SAcE,MAdF,CAAK,UAAU,8BAAf,SAcE,CAbA,SAKE,SALF,CACE,QAAS,IAAM,EAAY,EAAK,EAChC,UAAU,gEAFZ,wCAKE,EACF,SAME,SANF,CACE,QAAS,EACT,SAAU,CAAC,GAAY,CAAC,EACxB,UAAU,kHAHZ,SAKG,EAAc,OAAS,UAL1B,qBAME,IAbJ,qBAcE,IAvDJ,qBAwDE,GAzDJ,qBA0DE,IA1RN,qBA4RE",
8
+ "debugId": "395511E423F4574664756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{R as P}from"./App.p0fb1pds.js";import{S as N,V as Qq,W as c,Y as o,ca as E,fa as u}from"./App.mvtqv6qc.js";var K=N(Qq(),1);var z=N(c(),1);function i(W){let H=W.category==="LLM",X=W.category==="TOOL",M=W.level==="error",$=W.data?.input_tokens||0,Z=W.data?.output_tokens||0;return{llm_calls:H?1:0,tool_calls:X?1:0,errors:M?1:0,input_tokens:$,output_tokens:Z}}function _q(){let{events:W,statusChangeCounter:H}=o(),{currentProjectId:X,currentProject:M}=u(),{authFetch:$}=E(),[Z,l]=K.useState(null),[C,v]=K.useState([]),[I,d]=K.useState([]),[r,h]=K.useState(!0),[Y,p]=K.useState({level:"",agent_id:""}),[k,n]=K.useState(new Set(["DATABASE"])),[R,a]=K.useState([]),[S,s]=K.useState(null),T=K.useRef(new Set),[t,m]=K.useState(new Set),f=K.useRef(new Set);K.useEffect(()=>{(async()=>{try{let G=await(await $("/api/agents")).json();a(G.agents||[])}catch(B){console.error("Failed to fetch agents:",B)}})()},[$]);let w=K.useMemo(()=>{if(X===null)return R;if(X==="unassigned")return R.filter((q)=>!q.projectId);return R.filter((q)=>q.projectId===X)},[R,X]),V=K.useMemo(()=>new Set(w.map((q)=>q.id)),[w]),g=async()=>{h(!0);try{let q=X==="unassigned"?"null":X||"",B=new URLSearchParams;if(q)B.set("project_id",q);let Q=await(await $(`/api/telemetry/stats${B.toString()?`?${B}`:""}`)).json();l(Q.stats);let J=new URLSearchParams;if(Y.level)J.set("level",Y.level);if(Y.agent_id)J.set("agent_id",Y.agent_id);if(q)J.set("project_id",q);J.set("limit","100");let O=(await(await $(`/api/telemetry/events?${J}`)).json()).events||[];v(O),T.current=new Set(O.map((Kq)=>Kq.id));let b=new URLSearchParams;if(b.set("group_by","agent"),q)b.set("project_id",q);let Jq=await(await $(`/api/telemetry/usage?${b}`)).json();d(Jq.usage||[])}catch(q){console.error("Failed to fetch telemetry:",q)}h(!1)};K.useEffect(()=>{g()},[Y,X,$,H]);let U=K.useMemo(()=>{if(!Z)return null;let q=0,B=0,G=0,Q=0,J=0,A=0;for(let y of W)if(!T.current.has(y.id)){q++;let O=i(y);B+=O.llm_calls,G+=O.tool_calls,Q+=O.errors,J+=O.input_tokens,A+=O.output_tokens}return{total_events:Z.total_events+q,total_llm_calls:Z.total_llm_calls+B,total_tool_calls:Z.total_tool_calls+G,total_errors:Z.total_errors+Q,total_input_tokens:Z.total_input_tokens+J,total_output_tokens:Z.total_output_tokens+A}},[Z,W]),D=K.useMemo(()=>{let q=new Map;for(let B of I)q.set(B.agent_id,{...B});for(let B of W)if(!T.current.has(B.id)){let G=i(B),Q=q.get(B.agent_id);if(Q)Q.llm_calls+=G.llm_calls,Q.tool_calls+=G.tool_calls,Q.errors+=G.errors,Q.input_tokens+=G.input_tokens,Q.output_tokens+=G.output_tokens;else q.set(B.agent_id,{agent_id:B.agent_id,llm_calls:G.llm_calls,tool_calls:G.tool_calls,errors:G.errors,input_tokens:G.input_tokens,output_tokens:G.output_tokens})}return Array.from(q.values())},[I,W]),F=K.default.useMemo(()=>{let q=W;if(X!==null)q=q.filter((J)=>V.has(J.agent_id));if(Y.agent_id)q=q.filter((J)=>J.agent_id===Y.agent_id);if(k.size>0)q=q.filter((J)=>!k.has(J.category));if(Y.level)q=q.filter((J)=>J.level===Y.level);let B=C;if(k.size>0)B=B.filter((J)=>!k.has(J.category));let G=new Set(q.map((J)=>J.id)),Q=[...q];for(let J of B)if(!G.has(J.id))Q.push(J),G.add(J.id);return Q.sort((J,A)=>new Date(A.timestamp).getTime()-new Date(J.timestamp).getTime()),Q.slice(0,100)},[W,C,Y,k,X,V]);K.useEffect(()=>{let q=[];for(let B of W)if(!f.current.has(B.id))f.current.add(B.id),q.push(B.id);if(q.length>0)m((B)=>{let G=new Set(B);return q.forEach((Q)=>G.add(Q)),G}),setTimeout(()=>{m((B)=>{let G=new Set(B);return q.forEach((Q)=>G.delete(Q)),G})},5000)},[W]);let x=(q)=>{return R.find((G)=>G.id===q)?.name||q},_=(q)=>{if(q>=1e6)return(q/1e6).toFixed(1)+"M";if(q>=1000)return(q/1000).toFixed(1)+"K";return q.toString()},e={debug:"text-[#555]",info:"text-blue-400",warn:"text-yellow-400",error:"text-red-400"},j={LLM:"bg-purple-500/20 text-purple-400 border-purple-500/30",TOOL:"bg-blue-500/20 text-blue-400 border-blue-500/30",CHAT:"bg-green-500/20 text-green-400 border-green-500/30",ERROR:"bg-red-500/20 text-red-400 border-red-500/30",SYSTEM:"bg-gray-500/20 text-gray-400 border-gray-500/30",TASK:"bg-yellow-500/20 text-yellow-400 border-yellow-500/30",MEMORY:"bg-cyan-500/20 text-cyan-400 border-cyan-500/30",MCP:"bg-orange-500/20 text-orange-400 border-orange-500/30",DATABASE:"bg-pink-500/20 text-pink-400 border-pink-500/30"},qq=["LLM","TOOL","CHAT","TASK","MEMORY","MCP","SYSTEM","DATABASE","ERROR"],zq=(q)=>{n((B)=>{let G=new Set(B);if(G.has(q))G.delete(q);else G.add(q);return G})},Bq=[{value:"",label:"All Agents"},...w.map((q)=>({value:q.id,label:q.name}))],Gq=[{value:"",label:"All Levels"},{value:"debug",label:"Debug"},{value:"info",label:"Info"},{value:"warn",label:"Warn"},{value:"error",label:"Error"}];return z.jsxDEV("div",{className:"flex-1 overflow-auto p-6",children:z.jsxDEV("div",{children:[z.jsxDEV("div",{className:"mb-6",children:[z.jsxDEV("div",{className:"flex items-center gap-3 mb-1",children:[M&&z.jsxDEV("span",{className:"w-3 h-3 rounded-full",style:{backgroundColor:M.color}},void 0,!1,void 0,this),z.jsxDEV("h1",{className:"text-2xl font-semibold",children:X===null?"Telemetry":X==="unassigned"?"Telemetry - Unassigned":`Telemetry - ${M?.name||""}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("p",{className:"text-[#666]",children:"Monitor agent activity, token usage, and errors."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U&&z.jsxDEV("div",{className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-6",children:[z.jsxDEV(L,{label:"Events",value:_(U.total_events)},void 0,!1,void 0,this),z.jsxDEV(L,{label:"LLM Calls",value:_(U.total_llm_calls)},void 0,!1,void 0,this),z.jsxDEV(L,{label:"Tool Calls",value:_(U.total_tool_calls)},void 0,!1,void 0,this),z.jsxDEV(L,{label:"Errors",value:_(U.total_errors),color:"red"},void 0,!1,void 0,this),z.jsxDEV(L,{label:"Input Tokens",value:_(U.total_input_tokens)},void 0,!1,void 0,this),z.jsxDEV(L,{label:"Output Tokens",value:_(U.total_output_tokens)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D.length>0&&z.jsxDEV("div",{className:"mb-6",children:[z.jsxDEV("h2",{className:"text-lg font-medium mb-3",children:"Usage by Agent"},void 0,!1,void 0,this),z.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg overflow-hidden",children:z.jsxDEV("table",{className:"w-full text-sm",children:[z.jsxDEV("thead",{children:z.jsxDEV("tr",{className:"border-b border-[#1a1a1a] text-[#666]",children:[z.jsxDEV("th",{className:"text-left p-3",children:"Agent"},void 0,!1,void 0,this),z.jsxDEV("th",{className:"text-right p-3",children:"LLM Calls"},void 0,!1,void 0,this),z.jsxDEV("th",{className:"text-right p-3",children:"Tool Calls"},void 0,!1,void 0,this),z.jsxDEV("th",{className:"text-right p-3",children:"Input Tokens"},void 0,!1,void 0,this),z.jsxDEV("th",{className:"text-right p-3",children:"Output Tokens"},void 0,!1,void 0,this),z.jsxDEV("th",{className:"text-right p-3",children:"Errors"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("tbody",{children:D.map((q)=>z.jsxDEV("tr",{className:"border-b border-[#1a1a1a] last:border-0",children:[z.jsxDEV("td",{className:"p-3 font-medium",children:x(q.agent_id)},void 0,!1,void 0,this),z.jsxDEV("td",{className:"p-3 text-right text-[#888]",children:_(q.llm_calls)},void 0,!1,void 0,this),z.jsxDEV("td",{className:"p-3 text-right text-[#888]",children:_(q.tool_calls)},void 0,!1,void 0,this),z.jsxDEV("td",{className:"p-3 text-right text-[#888]",children:_(q.input_tokens)},void 0,!1,void 0,this),z.jsxDEV("td",{className:"p-3 text-right text-[#888]",children:_(q.output_tokens)},void 0,!1,void 0,this),z.jsxDEV("td",{className:"p-3 text-right",children:q.errors>0?z.jsxDEV("span",{className:"text-red-400",children:q.errors},void 0,!1,void 0,this):z.jsxDEV("span",{className:"text-[#444]",children:"0"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},q.agent_id,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"flex flex-wrap items-center gap-3 mb-4",children:[z.jsxDEV("div",{className:"w-44",children:z.jsxDEV(P,{value:Y.agent_id,options:Bq,onChange:(q)=>p({...Y,agent_id:q}),placeholder:"All Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex flex-wrap items-center gap-1.5 flex-1",children:qq.map((q)=>{let B=k.has(q),G=j[q]||"bg-[#222] text-[#888] border-[#333]";return z.jsxDEV("button",{onClick:()=>zq(q),className:`px-2 py-0.5 rounded text-xs border transition-all ${B?"bg-[#1a1a1a] text-[#555] border-[#333] opacity-50":G}`,children:q},q,!1,void 0,this)})},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex items-center gap-2",children:[z.jsxDEV("div",{className:"w-36",children:z.jsxDEV(P,{value:Y.level,options:Gq,onChange:(q)=>p({...Y,level:q}),placeholder:"All Levels"},void 0,!1,void 0,this)},void 0,!1,void 0,this),z.jsxDEV("button",{onClick:g,className:"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] border border-[#333] rounded text-sm transition",children:"Refresh"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg",children:[z.jsxDEV("div",{className:"p-3 border-b border-[#1a1a1a] flex items-center justify-between",children:[z.jsxDEV("h2",{className:"font-medium",children:"Recent Events"},void 0,!1,void 0,this),W.length>0&&z.jsxDEV("span",{className:"text-xs text-[#666]",children:[W.length," new"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),r&&F.length===0?z.jsxDEV("div",{className:"p-8 text-center text-[#666]",children:"Loading..."},void 0,!1,void 0,this):F.length===0?z.jsxDEV("div",{className:"p-8 text-center text-[#666]",children:"No telemetry events yet. Events will appear here in real-time once agents start sending data."},void 0,!1,void 0,this):z.jsxDEV("div",{className:"divide-y divide-[#1a1a1a]",children:F.map((q)=>{let B=t.has(q.id);return z.jsxDEV("div",{className:`p-3 hover:bg-[#0a0a0a] cursor-pointer transition-all duration-500 ${B?"bg-green-500/5":""}`,style:{animation:B?"slideIn 0.3s ease-out":void 0},onClick:()=>s(S===q.id?null:q.id),children:z.jsxDEV("div",{className:"flex items-start gap-3",children:[z.jsxDEV("span",{className:`px-2 py-0.5 rounded text-xs border transition-colors duration-300 ${j[q.category]||"bg-[#222] text-[#888] border-[#333]"}`,children:q.category},void 0,!1,void 0,this),z.jsxDEV("div",{className:"flex-1 min-w-0",children:[z.jsxDEV("div",{className:"flex items-center gap-2",children:[z.jsxDEV("span",{className:"font-medium text-sm",children:q.type},void 0,!1,void 0,this),z.jsxDEV("span",{className:`text-xs ${e[q.level]||"text-[#666]"}`,children:q.level},void 0,!1,void 0,this),q.duration_ms&&z.jsxDEV("span",{className:"text-xs text-[#555]",children:[q.duration_ms,"ms"]},void 0,!0,void 0,this),z.jsxDEV("span",{className:`w-1.5 h-1.5 rounded-full bg-green-400 transition-opacity duration-1000 ${B?"opacity-100":"opacity-0"}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z.jsxDEV("div",{className:"text-xs text-[#555] mt-1",children:[x(q.agent_id)," · ",new Date(q.timestamp).toLocaleString()]},void 0,!0,void 0,this),q.error&&z.jsxDEV("div",{className:"text-xs text-red-400 mt-1 font-mono",children:q.error},void 0,!1,void 0,this),S===q.id&&q.data&&Object.keys(q.data).length>0&&z.jsxDEV("pre",{className:"text-xs text-[#666] mt-2 p-2 bg-[#0a0a0a] rounded overflow-x-auto",children:JSON.stringify(q.data,null,2)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},q.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)}function L({label:W,value:H,color:X}){return z.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-4",children:[z.jsxDEV("div",{className:"text-[#666] text-xs mb-1",children:W},void 0,!1,void 0,this),z.jsxDEV("div",{className:`text-2xl font-semibold ${X==="red"?"text-red-400":""}`,children:H},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}
2
+ export{_q as Q};
3
+
4
+ //# debugId=95CAF9676B21055C64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/telemetry/TelemetryPage.tsx"],
4
+ "sourcesContent": [
5
+ "import React, { useState, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { Select } from \"../common/Select\";\nimport { useTelemetryContext, useProjects, useAuth, type TelemetryEvent } from \"../../context\";\n\ninterface TelemetryStats {\n total_events: number;\n total_llm_calls: number;\n total_tool_calls: number;\n total_errors: number;\n total_input_tokens: number;\n total_output_tokens: number;\n}\n\ninterface UsageByAgent {\n agent_id: string;\n input_tokens: number;\n output_tokens: number;\n llm_calls: number;\n tool_calls: number;\n errors: number;\n}\n\n// Helper to extract stats from a single event\nfunction extractEventStats(event: TelemetryEvent): {\n llm_calls: number;\n tool_calls: number;\n errors: number;\n input_tokens: number;\n output_tokens: number;\n} {\n const isLlm = event.category === \"LLM\";\n const isTool = event.category === \"TOOL\";\n const isError = event.level === \"error\";\n const inputTokens = (event.data?.input_tokens as number) || 0;\n const outputTokens = (event.data?.output_tokens as number) || 0;\n\n return {\n llm_calls: isLlm ? 1 : 0,\n tool_calls: isTool ? 1 : 0,\n errors: isError ? 1 : 0,\n input_tokens: inputTokens,\n output_tokens: outputTokens,\n };\n}\n\nexport function TelemetryPage() {\n const { events: realtimeEvents, statusChangeCounter } = useTelemetryContext();\n const { currentProjectId, currentProject } = useProjects();\n const { authFetch } = useAuth();\n const [fetchedStats, setFetchedStats] = useState<TelemetryStats | null>(null);\n const [historicalEvents, setHistoricalEvents] = useState<TelemetryEvent[]>([]);\n const [fetchedUsage, setFetchedUsage] = useState<UsageByAgent[]>([]);\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState({\n level: \"\",\n agent_id: \"\",\n });\n // Categories to hide (DATABASE hidden by default)\n const [hiddenCategories, setHiddenCategories] = useState<Set<string>>(new Set([\"DATABASE\"]));\n const [agents, setAgents] = useState<Array<{ id: string; name: string; projectId: string | null }>>([]);\n const [expandedEvent, setExpandedEvent] = useState<string | null>(null);\n\n // Track IDs that were in the fetched stats to avoid double-counting\n const countedEventIdsRef = useRef<Set<string>>(new Set());\n\n // Track which events are \"new\" (for animation) - stores event IDs with their arrival time\n const [newEventIds, setNewEventIds] = useState<Set<string>>(new Set());\n const seenEventIdsRef = useRef<Set<string>>(new Set());\n\n // Fetch agents for dropdown\n useEffect(() => {\n const fetchAgents = async () => {\n try {\n const res = await authFetch(\"/api/agents\");\n const data = await res.json();\n setAgents(data.agents || []);\n } catch (e) {\n console.error(\"Failed to fetch agents:\", e);\n }\n };\n fetchAgents();\n }, [authFetch]);\n\n // Filter agents by project\n const filteredAgents = useMemo(() => {\n if (currentProjectId === null) return agents;\n if (currentProjectId === \"unassigned\") return agents.filter(a => !a.projectId);\n return agents.filter(a => a.projectId === currentProjectId);\n }, [agents, currentProjectId]);\n\n // Get agent IDs for the current project\n const projectAgentIds = useMemo(() => new Set(filteredAgents.map(a => a.id)), [filteredAgents]);\n\n // Fetch stats and historical data (less frequently now since we have real-time)\n const fetchData = async () => {\n setLoading(true);\n try {\n // Build project filter param\n const projectParam = currentProjectId === \"unassigned\" ? \"null\" : currentProjectId || \"\";\n\n // Fetch stats\n const statsParams = new URLSearchParams();\n if (projectParam) statsParams.set(\"project_id\", projectParam);\n const statsRes = await authFetch(`/api/telemetry/stats${statsParams.toString() ? `?${statsParams}` : \"\"}`);\n const statsData = await statsRes.json();\n setFetchedStats(statsData.stats);\n\n // Fetch historical events with filters\n const params = new URLSearchParams();\n if (filter.level) params.set(\"level\", filter.level);\n if (filter.agent_id) params.set(\"agent_id\", filter.agent_id);\n if (projectParam) params.set(\"project_id\", projectParam);\n params.set(\"limit\", \"100\"); // Fetch more since we filter client-side\n\n const eventsRes = await authFetch(`/api/telemetry/events?${params}`);\n const eventsData = await eventsRes.json();\n const events = eventsData.events || [];\n setHistoricalEvents(events);\n\n // Mark all fetched event IDs as counted (stats already include them)\n countedEventIdsRef.current = new Set(events.map((e: TelemetryEvent) => e.id));\n\n // Fetch usage by agent\n const usageParams = new URLSearchParams();\n usageParams.set(\"group_by\", \"agent\");\n if (projectParam) usageParams.set(\"project_id\", projectParam);\n const usageRes = await authFetch(`/api/telemetry/usage?${usageParams}`);\n const usageData = await usageRes.json();\n setFetchedUsage(usageData.usage || []);\n } catch (e) {\n console.error(\"Failed to fetch telemetry:\", e);\n }\n setLoading(false);\n };\n\n useEffect(() => {\n fetchData();\n }, [filter, currentProjectId, authFetch, statusChangeCounter]);\n\n // Compute real-time stats from new events (not already counted in fetched stats)\n const stats = useMemo(() => {\n if (!fetchedStats) return null;\n\n // Calculate deltas from real-time events not in fetched data\n let deltaEvents = 0;\n let deltaLlmCalls = 0;\n let deltaToolCalls = 0;\n let deltaErrors = 0;\n let deltaInputTokens = 0;\n let deltaOutputTokens = 0;\n\n for (const event of realtimeEvents) {\n if (!countedEventIdsRef.current.has(event.id)) {\n deltaEvents++;\n const eventStats = extractEventStats(event);\n deltaLlmCalls += eventStats.llm_calls;\n deltaToolCalls += eventStats.tool_calls;\n deltaErrors += eventStats.errors;\n deltaInputTokens += eventStats.input_tokens;\n deltaOutputTokens += eventStats.output_tokens;\n }\n }\n\n return {\n total_events: fetchedStats.total_events + deltaEvents,\n total_llm_calls: fetchedStats.total_llm_calls + deltaLlmCalls,\n total_tool_calls: fetchedStats.total_tool_calls + deltaToolCalls,\n total_errors: fetchedStats.total_errors + deltaErrors,\n total_input_tokens: fetchedStats.total_input_tokens + deltaInputTokens,\n total_output_tokens: fetchedStats.total_output_tokens + deltaOutputTokens,\n };\n }, [fetchedStats, realtimeEvents]);\n\n // Compute real-time usage by agent\n const usage = useMemo(() => {\n // Start with a copy of fetched usage as a map\n const usageMap = new Map<string, UsageByAgent>();\n for (const u of fetchedUsage) {\n usageMap.set(u.agent_id, { ...u });\n }\n\n // Add deltas from real-time events\n for (const event of realtimeEvents) {\n if (!countedEventIdsRef.current.has(event.id)) {\n const eventStats = extractEventStats(event);\n const existing = usageMap.get(event.agent_id);\n if (existing) {\n existing.llm_calls += eventStats.llm_calls;\n existing.tool_calls += eventStats.tool_calls;\n existing.errors += eventStats.errors;\n existing.input_tokens += eventStats.input_tokens;\n existing.output_tokens += eventStats.output_tokens;\n } else {\n usageMap.set(event.agent_id, {\n agent_id: event.agent_id,\n llm_calls: eventStats.llm_calls,\n tool_calls: eventStats.tool_calls,\n errors: eventStats.errors,\n input_tokens: eventStats.input_tokens,\n output_tokens: eventStats.output_tokens,\n });\n }\n }\n }\n\n return Array.from(usageMap.values());\n }, [fetchedUsage, realtimeEvents]);\n\n // Merge real-time events with historical, filtering and deduping\n const allEvents = React.useMemo(() => {\n // Apply filters to real-time events\n let filtered = realtimeEvents;\n\n // Filter by project (for real-time events)\n if (currentProjectId !== null) {\n filtered = filtered.filter(e => projectAgentIds.has(e.agent_id));\n }\n\n if (filter.agent_id) {\n filtered = filtered.filter(e => e.agent_id === filter.agent_id);\n }\n // Filter out hidden categories\n if (hiddenCategories.size > 0) {\n filtered = filtered.filter(e => !hiddenCategories.has(e.category));\n }\n if (filter.level) {\n filtered = filtered.filter(e => e.level === filter.level);\n }\n\n // Filter historical events too\n let filteredHistorical = historicalEvents;\n if (hiddenCategories.size > 0) {\n filteredHistorical = filteredHistorical.filter(e => !hiddenCategories.has(e.category));\n }\n\n // Merge with historical, dedupe by ID\n const seen = new Set(filtered.map(e => e.id));\n const merged = [...filtered];\n for (const evt of filteredHistorical) {\n if (!seen.has(evt.id)) {\n merged.push(evt);\n seen.add(evt.id);\n }\n }\n\n // Sort by timestamp descending\n merged.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n\n return merged.slice(0, 100);\n }, [realtimeEvents, historicalEvents, filter, hiddenCategories, currentProjectId, projectAgentIds]);\n\n // Track new events for animation - mark events as \"new\" when they first appear\n useEffect(() => {\n const newIds: string[] = [];\n for (const event of realtimeEvents) {\n if (!seenEventIdsRef.current.has(event.id)) {\n seenEventIdsRef.current.add(event.id);\n newIds.push(event.id);\n }\n }\n\n if (newIds.length > 0) {\n setNewEventIds(prev => {\n const updated = new Set(prev);\n newIds.forEach(id => updated.add(id));\n return updated;\n });\n\n // Remove \"new\" status after 5 seconds\n setTimeout(() => {\n setNewEventIds(prev => {\n const updated = new Set(prev);\n newIds.forEach(id => updated.delete(id));\n return updated;\n });\n }, 5000);\n }\n }, [realtimeEvents]);\n\n const getAgentName = (agentId: string) => {\n const agent = agents.find(a => a.id === agentId);\n return agent?.name || agentId;\n };\n\n const formatNumber = (n: number) => {\n if (n >= 1000000) return (n / 1000000).toFixed(1) + \"M\";\n if (n >= 1000) return (n / 1000).toFixed(1) + \"K\";\n return n.toString();\n };\n\n const levelColors: Record<string, string> = {\n debug: \"text-[#555]\",\n info: \"text-blue-400\",\n warn: \"text-yellow-400\",\n error: \"text-red-400\",\n };\n\n const categoryColors: Record<string, string> = {\n LLM: \"bg-purple-500/20 text-purple-400 border-purple-500/30\",\n TOOL: \"bg-blue-500/20 text-blue-400 border-blue-500/30\",\n CHAT: \"bg-green-500/20 text-green-400 border-green-500/30\",\n ERROR: \"bg-red-500/20 text-red-400 border-red-500/30\",\n SYSTEM: \"bg-gray-500/20 text-gray-400 border-gray-500/30\",\n TASK: \"bg-yellow-500/20 text-yellow-400 border-yellow-500/30\",\n MEMORY: \"bg-cyan-500/20 text-cyan-400 border-cyan-500/30\",\n MCP: \"bg-orange-500/20 text-orange-400 border-orange-500/30\",\n DATABASE: \"bg-pink-500/20 text-pink-400 border-pink-500/30\",\n };\n\n const allCategories = [\"LLM\", \"TOOL\", \"CHAT\", \"TASK\", \"MEMORY\", \"MCP\", \"SYSTEM\", \"DATABASE\", \"ERROR\"];\n\n const toggleCategory = (category: string) => {\n setHiddenCategories(prev => {\n const updated = new Set(prev);\n if (updated.has(category)) {\n updated.delete(category);\n } else {\n updated.add(category);\n }\n return updated;\n });\n };\n\n const agentOptions = [\n { value: \"\", label: \"All Agents\" },\n ...filteredAgents.map(a => ({ value: a.id, label: a.name })),\n ];\n\n const levelOptions = [\n { value: \"\", label: \"All Levels\" },\n { value: \"debug\", label: \"Debug\" },\n { value: \"info\", label: \"Info\" },\n { value: \"warn\", label: \"Warn\" },\n { value: \"error\", label: \"Error\" },\n ];\n\n return (\n <div className=\"flex-1 overflow-auto p-6\">\n <div>\n {/* Header */}\n <div className=\"mb-6\">\n <div className=\"flex items-center gap-3 mb-1\">\n {currentProject && (\n <span\n className=\"w-3 h-3 rounded-full\"\n style={{ backgroundColor: currentProject.color }}\n />\n )}\n <h1 className=\"text-2xl font-semibold\">\n {currentProjectId === null\n ? \"Telemetry\"\n : currentProjectId === \"unassigned\"\n ? \"Telemetry - Unassigned\"\n : `Telemetry - ${currentProject?.name || \"\"}`}\n </h1>\n </div>\n <p className=\"text-[#666]\">\n Monitor agent activity, token usage, and errors.\n </p>\n </div>\n\n {/* Stats Cards */}\n {stats && (\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-6\">\n <StatCard label=\"Events\" value={formatNumber(stats.total_events)} />\n <StatCard label=\"LLM Calls\" value={formatNumber(stats.total_llm_calls)} />\n <StatCard label=\"Tool Calls\" value={formatNumber(stats.total_tool_calls)} />\n <StatCard label=\"Errors\" value={formatNumber(stats.total_errors)} color=\"red\" />\n <StatCard label=\"Input Tokens\" value={formatNumber(stats.total_input_tokens)} />\n <StatCard label=\"Output Tokens\" value={formatNumber(stats.total_output_tokens)} />\n </div>\n )}\n\n {/* Usage by Agent */}\n {usage.length > 0 && (\n <div className=\"mb-6\">\n <h2 className=\"text-lg font-medium mb-3\">Usage by Agent</h2>\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-[#1a1a1a] text-[#666]\">\n <th className=\"text-left p-3\">Agent</th>\n <th className=\"text-right p-3\">LLM Calls</th>\n <th className=\"text-right p-3\">Tool Calls</th>\n <th className=\"text-right p-3\">Input Tokens</th>\n <th className=\"text-right p-3\">Output Tokens</th>\n <th className=\"text-right p-3\">Errors</th>\n </tr>\n </thead>\n <tbody>\n {usage.map((u) => (\n <tr key={u.agent_id} className=\"border-b border-[#1a1a1a] last:border-0\">\n <td className=\"p-3 font-medium\">{getAgentName(u.agent_id)}</td>\n <td className=\"p-3 text-right text-[#888]\">{formatNumber(u.llm_calls)}</td>\n <td className=\"p-3 text-right text-[#888]\">{formatNumber(u.tool_calls)}</td>\n <td className=\"p-3 text-right text-[#888]\">{formatNumber(u.input_tokens)}</td>\n <td className=\"p-3 text-right text-[#888]\">{formatNumber(u.output_tokens)}</td>\n <td className=\"p-3 text-right\">\n {u.errors > 0 ? (\n <span className=\"text-red-400\">{u.errors}</span>\n ) : (\n <span className=\"text-[#444]\">0</span>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-3 mb-4\">\n <div className=\"w-44\">\n <Select\n value={filter.agent_id}\n options={agentOptions}\n onChange={(value) => setFilter({ ...filter, agent_id: value })}\n placeholder=\"All Agents\"\n />\n </div>\n {/* Category toggles */}\n <div className=\"flex flex-wrap items-center gap-1.5 flex-1\">\n {allCategories.map((cat) => {\n const isHidden = hiddenCategories.has(cat);\n const colorClass = categoryColors[cat] || \"bg-[#222] text-[#888] border-[#333]\";\n return (\n <button\n key={cat}\n onClick={() => toggleCategory(cat)}\n className={`px-2 py-0.5 rounded text-xs border transition-all ${\n isHidden\n ? \"bg-[#1a1a1a] text-[#555] border-[#333] opacity-50\"\n : colorClass\n }`}\n >\n {cat}\n </button>\n );\n })}\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-36\">\n <Select\n value={filter.level}\n options={levelOptions}\n onChange={(value) => setFilter({ ...filter, level: value })}\n placeholder=\"All Levels\"\n />\n </div>\n <button\n onClick={fetchData}\n className=\"px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] border border-[#333] rounded text-sm transition\"\n >\n Refresh\n </button>\n </div>\n </div>\n\n {/* Events List */}\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg\">\n <div className=\"p-3 border-b border-[#1a1a1a] flex items-center justify-between\">\n <h2 className=\"font-medium\">Recent Events</h2>\n {realtimeEvents.length > 0 && (\n <span className=\"text-xs text-[#666]\">\n {realtimeEvents.length} new\n </span>\n )}\n </div>\n\n {loading && allEvents.length === 0 ? (\n <div className=\"p-8 text-center text-[#666]\">Loading...</div>\n ) : allEvents.length === 0 ? (\n <div className=\"p-8 text-center text-[#666]\">\n No telemetry events yet. Events will appear here in real-time once agents start sending data.\n </div>\n ) : (\n <div className=\"divide-y divide-[#1a1a1a]\">\n {allEvents.map((event) => {\n const isNew = newEventIds.has(event.id);\n\n return (\n <div\n key={event.id}\n className={`p-3 hover:bg-[#0a0a0a] cursor-pointer transition-all duration-500 ${\n isNew ? \"bg-green-500/5\" : \"\"\n }`}\n style={{\n animation: isNew ? \"slideIn 0.3s ease-out\" : undefined,\n }}\n onClick={() => setExpandedEvent(expandedEvent === event.id ? null : event.id)}\n >\n <div className=\"flex items-start gap-3\">\n <span className={`px-2 py-0.5 rounded text-xs border transition-colors duration-300 ${categoryColors[event.category] || \"bg-[#222] text-[#888] border-[#333]\"}`}>\n {event.category}\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{event.type}</span>\n <span className={`text-xs ${levelColors[event.level] || \"text-[#666]\"}`}>\n {event.level}\n </span>\n {event.duration_ms && (\n <span className=\"text-xs text-[#555]\">{event.duration_ms}ms</span>\n )}\n <span\n className={`w-1.5 h-1.5 rounded-full bg-green-400 transition-opacity duration-1000 ${\n isNew ? \"opacity-100\" : \"opacity-0\"\n }`}\n />\n </div>\n <div className=\"text-xs text-[#555] mt-1\">\n {getAgentName(event.agent_id)} · {new Date(event.timestamp).toLocaleString()}\n </div>\n {event.error && (\n <div className=\"text-xs text-red-400 mt-1 font-mono\">{event.error}</div>\n )}\n {expandedEvent === event.id && event.data && Object.keys(event.data).length > 0 && (\n <pre className=\"text-xs text-[#666] mt-2 p-2 bg-[#0a0a0a] rounded overflow-x-auto\">\n {JSON.stringify(event.data, null, 2)}\n </pre>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction StatCard({ label, value, color }: { label: string; value: string; color?: string }) {\n return (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4\">\n <div className=\"text-[#666] text-xs mb-1\">{label}</div>\n <div className={`text-2xl font-semibold ${color === \"red\" ? \"text-red-400\" : \"\"}`}>\n {value}\n </div>\n </div>\n );\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "95CAF9676B21055C64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{H as u,I as c,J as E}from"./App.ncgc9cxy.js";import{S as A,V as a,W as h,Y as V,Z as x,_ as D,ca as T,fa as j}from"./App.mvtqv6qc.js";var X=A(a(),1);var q=A(h(),1);function Qq({agents:B,loading:Z,onNavigate:L}){let{authFetch:G}=T(),{currentProjectId:J}=j(),{events:$,statusChangeCounter:K}=V(),[H,Q]=X.useState(null),[W,U]=X.useState([]),[O,P]=X.useState([]),I=X.useRef(null),{events:R}=x({category:"TASK"}),N=X.useMemo(()=>{if(J===null)return B;if(J==="unassigned")return B.filter((z)=>!z.projectId);return B.filter((z)=>z.projectId===J)},[B,J]),b=X.useMemo(()=>{return[...N].sort((z,Y)=>{if(z.status==="running"&&Y.status!=="running")return-1;if(Y.status==="running"&&z.status!=="running")return 1;return z.name.localeCompare(Y.name)})},[N]),g=X.useMemo(()=>N.filter((z)=>z.status==="running").length,[N]),f=X.useMemo(()=>new Set(N.map((z)=>z.id)),[N]),d=X.useMemo(()=>{let z=new Map;return N.forEach((Y)=>z.set(Y.id,Y.name)),z},[N]),M=X.useCallback(async()=>{let z=J?`&project_id=${encodeURIComponent(J)}`:"",[Y,p]=await Promise.all([G(`/api/tasks?status=all${z}`).catch(()=>null),G(`/api/telemetry/events?type=thread_activity&limit=50${z}`).catch(()=>null)]);if(Y?.ok){let _=(await Y.json()).tasks||[];_.sort((F,w)=>{let S=F.status==="running"?0:F.status==="pending"?1:F.status==="completed"?2:3,v=w.status==="running"?0:w.status==="pending"?1:w.status==="completed"?2:3;if(S!==v)return S-v;if(S<=1){let r=F.next_run||F.execute_at?new Date(F.next_run||F.execute_at).getTime():1/0,n=w.next_run||w.execute_at?new Date(w.next_run||w.execute_at).getTime():1/0;return r-n}let o=F.completed_at||F.executed_at||F.created_at,i=w.completed_at||w.executed_at||w.created_at;return new Date(i).getTime()-new Date(o).getTime()}),U(_)}if(p?.ok){let C=await p.json();P(C.events||[])}},[G,J]);X.useEffect(()=>{M()},[M,K]),X.useEffect(()=>{if(!R.length)return;let z=R[0];if(!z||z.id===I.current)return;let Y=z.type;if(Y==="task_created"||Y==="task_updated"||Y==="task_deleted")I.current=z.id,M()},[R,M]);let y=X.useMemo(()=>{let z=$.filter((_)=>_.type==="thread_activity"),Y=new Set(z.map((_)=>_.id)),p=[...z];for(let _ of O)if(!Y.has(_.id))p.push(_),Y.add(_.id);let C=p.filter((_)=>f.has(_.agent_id));return C.sort((_,F)=>new Date(F.timestamp).getTime()-new Date(_.timestamp).getTime()),C.slice(0,50)},[$,O,f]);if(Z)return q.jsxDEV("div",{className:"flex-1 flex items-center justify-center text-[#666]",children:"Loading..."},void 0,!1,void 0,this);return q.jsxDEV("div",{className:"flex-1 flex flex-col overflow-hidden",children:[q.jsxDEV("div",{className:"px-6 pt-6 pb-4 shrink-0",children:q.jsxDEV("div",{className:"flex items-center justify-between",children:[q.jsxDEV("h1",{className:"text-xl font-semibold",children:"Activity"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-sm text-[#666]",children:[g," of ",N.length," agents running"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex-1 flex min-h-0 overflow-hidden",children:[q.jsxDEV("div",{className:"flex-[2] flex flex-col overflow-hidden border-r border-[#1a1a1a]",children:[q.jsxDEV("div",{className:"px-4 py-2.5 border-b border-[#1a1a1a] shrink-0",children:q.jsxDEV("h3",{className:"text-xs font-semibold text-[#666] uppercase tracking-wider",children:"Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex-1 overflow-auto px-3 py-2",children:[b.length===0?q.jsxDEV("p",{className:"text-sm text-[#555] px-2 py-4 text-center",children:"No agents found"},void 0,!1,void 0,this):q.jsxDEV("div",{className:"space-y-1",children:b.map((z)=>q.jsxDEV(s,{agent:z,selected:H===z.id,onSelect:()=>Q(H===z.id?null:z.id)},z.id,!1,void 0,this))},void 0,!1,void 0,this),H&&q.jsxDEV(t,{agent:N.find((z)=>z.id===H)||null},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex-[3] flex flex-col min-h-0 overflow-hidden border-r border-[#1a1a1a]",children:[q.jsxDEV("div",{className:"px-4 py-2.5 border-b border-[#1a1a1a] flex items-center justify-between shrink-0",children:[q.jsxDEV("h3",{className:"text-xs font-semibold text-[#666] uppercase tracking-wider",children:"Activity Feed"},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-xs text-[#555]",children:y.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex-1 overflow-auto",children:y.length===0?q.jsxDEV("div",{className:"p-6 text-center text-[#555] text-sm",children:"No activity yet. Agent activity will appear here in real-time."},void 0,!1,void 0,this):q.jsxDEV("div",{className:"divide-y divide-[#1a1a1a]",children:y.map((z)=>q.jsxDEV("div",{className:"px-4 py-2.5 hover:bg-[#111]/50 transition",children:[q.jsxDEV("p",{className:"text-sm truncate",children:z.data?.activity||"Working..."},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex items-center gap-2 text-[10px] text-[#555] mt-0.5",children:[q.jsxDEV("span",{className:"text-[#666]",children:d.get(z.agent_id)||z.agent_id},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[#444]",children:"·"},void 0,!1,void 0,this),q.jsxDEV("span",{children:zq(z.timestamp)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},z.id,!0,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex-[3] flex flex-col overflow-hidden",children:[q.jsxDEV("div",{className:"px-4 py-2.5 border-b border-[#1a1a1a] flex items-center justify-between shrink-0",children:[q.jsxDEV("h3",{className:"text-xs font-semibold text-[#666] uppercase tracking-wider",children:"Tasks"},void 0,!1,void 0,this),L&&q.jsxDEV("button",{onClick:()=>L("tasks"),className:"text-xs text-[#3b82f6] hover:text-[#60a5fa]",children:"View All"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex-1 overflow-auto px-3 py-3",children:W.length===0?q.jsxDEV("p",{className:"text-sm text-[#555] px-2 py-4 text-center",children:"No tasks yet"},void 0,!1,void 0,this):q.jsxDEV("div",{className:"space-y-2.5",children:W.map((z)=>q.jsxDEV(e,{task:z},`${z.agentId}-${z.id}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function s({agent:B,selected:Z,onSelect:L}){let{isActive:G,label:J}=D(B.id),$=B.status==="running";return q.jsxDEV("button",{onClick:L,className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition ${Z?"bg-[#f97316]/10 border border-[#f97316]/30":"hover:bg-[#1a1a1a] border border-transparent"}`,children:[q.jsxDEV("span",{className:`w-2.5 h-2.5 rounded-full shrink-0 ${$&&G?"bg-green-400 animate-pulse":$?"bg-[#3b82f6]":"bg-[#444]"}`},void 0,!1,void 0,this),q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("div",{className:"flex items-center gap-2",children:[q.jsxDEV("span",{className:`text-sm font-medium truncate ${$?"":"text-[#666]"}`,children:B.name},void 0,!1,void 0,this),q.jsxDEV("span",{className:"text-[10px] text-[#555] shrink-0",children:B.provider},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G&&J?q.jsxDEV("p",{className:"text-[11px] text-green-400 truncate",children:J},void 0,!1,void 0,this):q.jsxDEV("p",{className:`text-[11px] ${$?"text-[#555]":"text-[#444]"}`,children:$?"idle":"stopped"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function t({agent:B}){let{authFetch:Z}=T(),[L,G]=X.useState(""),[J,$]=X.useState(!1),[K,H]=X.useState(null);if(X.useEffect(()=>{G(""),H(null)},[B?.id]),!B)return null;let Q=B.status==="running",W=async()=>{if(!L.trim()||J)return;if(!Q){H("Agent is not running"),setTimeout(()=>H(null),3000);return}$(!0);try{let U=await Z(`/api/agents/${B.id}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:L,agent_id:B.id})});if(U.ok)H("Sent"),G("");else{let O=await U.json().catch(()=>({}));H(O.error||"Failed")}}catch{H("Failed to send")}finally{$(!1),setTimeout(()=>H(null),3000)}};return q.jsxDEV("div",{className:"mt-2 bg-[#0a0a0a] border border-[#1a1a1a] rounded-lg p-2.5",children:[q.jsxDEV("div",{className:"flex items-center justify-between mb-1.5",children:[q.jsxDEV("span",{className:"text-[10px] text-[#666]",children:["Send to ",q.jsxDEV("span",{className:"text-[#888]",children:B.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K&&q.jsxDEV("span",{className:`text-[10px] px-1.5 py-0.5 rounded ${K==="Sent"?"bg-green-500/10 text-green-400":"bg-red-500/10 text-red-400"}`,children:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex gap-1.5",children:[q.jsxDEV("input",{type:"text",value:L,onChange:(U)=>G(U.target.value),onKeyDown:(U)=>U.key==="Enter"&&W(),placeholder:Q?"Command...":"Not running",disabled:J||!Q,autoFocus:!0,className:"flex-1 bg-[#111] border border-[#1a1a1a] rounded px-2 py-1.5 text-xs focus:outline-none focus:border-[#f97316] placeholder-[#444] disabled:opacity-50"},void 0,!1,void 0,this),q.jsxDEV("button",{onClick:W,disabled:J||!L.trim()||!Q,className:"px-2.5 py-1.5 bg-[#f97316]/20 text-[#f97316] rounded text-xs font-medium hover:bg-[#f97316]/30 transition disabled:opacity-30",children:J?"...":"Send"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var k={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"},m=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function e({task:B}){return q.jsxDEV("div",{className:"bg-[#111] border border-[#1a1a1a] rounded-lg p-3 hover:border-[#333] transition",children:[q.jsxDEV("div",{className:"flex items-start justify-between mb-1.5",children:[q.jsxDEV("div",{className:"flex-1 min-w-0",children:[q.jsxDEV("h4",{className:"text-sm font-medium truncate",children:B.title},void 0,!1,void 0,this),q.jsxDEV("p",{className:"text-xs text-[#666]",children:B.agentName},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("span",{className:`px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ml-2 ${k[B.status]||k.pending}`,children:B.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q.jsxDEV("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-[#555]",children:[q.jsxDEV("span",{className:"flex items-center gap-1",children:[B.type==="recurring"?q.jsxDEV(u,{className:"w-3 h-3"},void 0,!1,void 0,this):B.execute_at?q.jsxDEV(c,{className:"w-3 h-3"},void 0,!1,void 0,this):q.jsxDEV(E,{className:"w-3 h-3"},void 0,!1,void 0,this),B.type==="recurring"&&B.recurrence?qq(B.recurrence):B.type]},void 0,!0,void 0,this),B.next_run&&q.jsxDEV("span",{className:"text-[#f97316]",children:l(B.next_run)},void 0,!1,void 0,this),!B.next_run&&B.execute_at&&q.jsxDEV("span",{className:"text-[#f97316]",children:l(B.execute_at)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function qq(B){try{let Z=B.trim().split(/\s+/);if(Z.length!==5)return B;let[L,G,J,$,K]=Z;if(L.startsWith("*/")&&G==="*"&&J==="*"&&$==="*"&&K==="*"){let Q=parseInt(L.slice(2));return Q===1?"Every min":`Every ${Q}min`}if(L!=="*"&&!L.includes("/")&&G==="*"&&J==="*"&&$==="*"&&K==="*")return"Hourly";if(G.startsWith("*/")&&J==="*"&&$==="*"&&K==="*"){let Q=parseInt(G.slice(2));return Q===1?"Hourly":`Every ${Q}h`}let H=(Q,W)=>{let U=parseInt(Q),O=parseInt(W);if(isNaN(U))return"";let P=U>=12?"PM":"AM";return`${U===0?12:U>12?U-12:U}:${O.toString().padStart(2,"0")} ${P}`};if(G!=="*"&&!G.includes("/")&&J==="*"&&$==="*"){let Q=H(G,L);if(K==="*")return`Daily ${Q}`;let W=K.split(",").map((U)=>m[parseInt(U.trim())]||U);if(W.length===1)return`${W[0]} ${Q}`;return`${W.join(", ")} ${Q}`}return B}catch{return B}}function l(B){let Z=new Date(B),L=new Date,G=Z.getTime()-L.getTime(),J=G>0,$=Math.abs(G),K=Math.floor($/60000),H=Math.floor($/3600000),Q=Z.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),W=Z.toDateString()===L.toDateString(),U=new Date(L);U.setDate(U.getDate()+1);let O=Z.toDateString()===U.toDateString();if(W){if(K<1)return"now";if(K<60)return J?`in ${K}m`:`${K}m ago`;return J?`in ${H}h (${Q})`:`${H}h ago`}if(O)return`Tomorrow ${Q}`;return`${m[Z.getDay()]} ${Q}`}function zq(B){let Z=Math.floor((Date.now()-new Date(B).getTime())/1000);if(Z<5)return"just now";if(Z<60)return`${Z}s ago`;let L=Math.floor(Z/60);if(L<60)return`${L}m ago`;let G=Math.floor(L/60);if(G<24)return`${G}h ago`;return`${Math.floor(G/24)}d ago`}
2
+ export{Qq as d};
3
+
4
+ //# debugId=A710C5DDE644C40564756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/web/components/activity/ActivityPage.tsx"],
4
+ "sourcesContent": [
5
+ "import React, { useState, useMemo, useEffect, useCallback, useRef } from \"react\";\nimport { useAgentActivity, useAuth, useProjects, useTelemetryContext } from \"../../context\";\nimport { useTelemetry } from \"../../context/TelemetryContext\";\nimport type { TelemetryEvent } from \"../../context\";\nimport type { Agent, Task, Route } from \"../../types\";\nimport { RecurringIcon, ScheduledIcon, TaskOnceIcon } from \"../common/Icons\";\n\ninterface ActivityPageProps {\n agents: Agent[];\n loading: boolean;\n onNavigate?: (route: Route) => void;\n}\n\nexport function ActivityPage({ agents, loading, onNavigate }: ActivityPageProps) {\n const { authFetch } = useAuth();\n const { currentProjectId } = useProjects();\n const { events: realtimeEvents, statusChangeCounter } = useTelemetryContext();\n const [selectedAgentId, setSelectedAgentId] = useState<string | null>(null);\n const [tasks, setTasks] = useState<Task[]>([]);\n const [historicalActivities, setHistoricalActivities] = useState<TelemetryEvent[]>([]);\n const lastProcessedTaskEventRef = useRef<string | null>(null);\n const { events: taskTelemetryEvents } = useTelemetry({ category: \"TASK\" });\n\n const filteredAgents = useMemo(() => {\n if (currentProjectId === null) return agents;\n if (currentProjectId === \"unassigned\") return agents.filter(a => !a.projectId);\n return agents.filter(a => a.projectId === currentProjectId);\n }, [agents, currentProjectId]);\n\n const sortedAgents = useMemo(() => {\n return [...filteredAgents].sort((a, b) => {\n if (a.status === \"running\" && b.status !== \"running\") return -1;\n if (b.status === \"running\" && a.status !== \"running\") return 1;\n return a.name.localeCompare(b.name);\n });\n }, [filteredAgents]);\n\n const runningCount = useMemo(() => filteredAgents.filter(a => a.status === \"running\").length, [filteredAgents]);\n\n const agentIds = useMemo(() => new Set(filteredAgents.map(a => a.id)), [filteredAgents]);\n const agentNameMap = useMemo(() => {\n const map = new Map<string, string>();\n filteredAgents.forEach(a => map.set(a.id, a.name));\n return map;\n }, [filteredAgents]);\n\n // Fetch tasks + historical activity\n const fetchData = useCallback(async () => {\n const projectParam = currentProjectId ? `&project_id=${encodeURIComponent(currentProjectId)}` : \"\";\n const [tasksRes, activityRes] = await Promise.all([\n authFetch(`/api/tasks?status=all${projectParam}`).catch(() => null),\n authFetch(`/api/telemetry/events?type=thread_activity&limit=50${projectParam}`).catch(() => null),\n ]);\n if (tasksRes?.ok) {\n const data = await tasksRes.json();\n const list: Task[] = data.tasks || [];\n list.sort((a, b) => {\n const aPri = a.status === \"running\" ? 0 : a.status === \"pending\" ? 1 : a.status === \"completed\" ? 2 : 3;\n const bPri = b.status === \"running\" ? 0 : b.status === \"pending\" ? 1 : b.status === \"completed\" ? 2 : 3;\n if (aPri !== bPri) return aPri - bPri;\n if (aPri <= 1) {\n const aTs = (a.next_run || a.execute_at) ? new Date(a.next_run || a.execute_at!).getTime() : Infinity;\n const bTs = (b.next_run || b.execute_at) ? new Date(b.next_run || b.execute_at!).getTime() : Infinity;\n return aTs - bTs;\n }\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 setTasks(list);\n }\n if (activityRes?.ok) {\n const data = await activityRes.json();\n setHistoricalActivities(data.events || []);\n }\n }, [authFetch, currentProjectId]);\n\n useEffect(() => {\n fetchData();\n }, [fetchData, statusChangeCounter]);\n\n // Real-time task updates from telemetry (same pattern as TasksPage)\n useEffect(() => {\n if (!taskTelemetryEvents.length) return;\n const latestEvent = taskTelemetryEvents[0];\n if (!latestEvent || latestEvent.id === lastProcessedTaskEventRef.current) return;\n const eventType = latestEvent.type;\n if (eventType === \"task_created\" || eventType === \"task_updated\" || eventType === \"task_deleted\") {\n lastProcessedTaskEventRef.current = latestEvent.id;\n fetchData();\n }\n }, [taskTelemetryEvents, fetchData]);\n\n // Merge realtime + historical thread_activity\n const activities = useMemo(() => {\n const realtimeThreadEvents = realtimeEvents.filter(e => e.type === \"thread_activity\");\n const seen = new Set(realtimeThreadEvents.map(e => e.id));\n const merged = [...realtimeThreadEvents];\n for (const evt of historicalActivities) {\n if (!seen.has(evt.id)) {\n merged.push(evt);\n seen.add(evt.id);\n }\n }\n let filtered = merged.filter(e => agentIds.has(e.agent_id));\n filtered.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n return filtered.slice(0, 50);\n }, [realtimeEvents, historicalActivities, agentIds]);\n\n if (loading) {\n return <div className=\"flex-1 flex items-center justify-center text-[#666]\">Loading...</div>;\n }\n\n return (\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Header */}\n <div className=\"px-6 pt-6 pb-4 shrink-0\">\n <div className=\"flex items-center justify-between\">\n <h1 className=\"text-xl font-semibold\">Activity</h1>\n <span className=\"text-sm text-[#666]\">\n {runningCount} of {filteredAgents.length} agents running\n </span>\n </div>\n </div>\n\n {/* Three-column layout: 1/4 | 3/8 | 3/8 */}\n <div className=\"flex-1 flex min-h-0 overflow-hidden\">\n {/* Left: Agents (1/4) */}\n <div className=\"flex-[2] flex flex-col overflow-hidden border-r border-[#1a1a1a]\">\n <div className=\"px-4 py-2.5 border-b border-[#1a1a1a] shrink-0\">\n <h3 className=\"text-xs font-semibold text-[#666] uppercase tracking-wider\">Agents</h3>\n </div>\n <div className=\"flex-1 overflow-auto px-3 py-2\">\n {sortedAgents.length === 0 ? (\n <p className=\"text-sm text-[#555] px-2 py-4 text-center\">No agents found</p>\n ) : (\n <div className=\"space-y-1\">\n {sortedAgents.map(agent => (\n <AgentRow\n key={agent.id}\n agent={agent}\n selected={selectedAgentId === agent.id}\n onSelect={() => setSelectedAgentId(selectedAgentId === agent.id ? null : agent.id)}\n />\n ))}\n </div>\n )}\n\n {selectedAgentId && (\n <InlineCommand\n agent={filteredAgents.find(a => a.id === selectedAgentId) || null}\n />\n )}\n </div>\n </div>\n\n {/* Center: Activity Feed (3/8) */}\n <div className=\"flex-[3] flex flex-col min-h-0 overflow-hidden border-r border-[#1a1a1a]\">\n <div className=\"px-4 py-2.5 border-b border-[#1a1a1a] flex items-center justify-between shrink-0\">\n <h3 className=\"text-xs font-semibold text-[#666] uppercase tracking-wider\">Activity Feed</h3>\n <span className=\"text-xs text-[#555]\">{activities.length}</span>\n </div>\n <div className=\"flex-1 overflow-auto\">\n {activities.length === 0 ? (\n <div className=\"p-6 text-center text-[#555] text-sm\">\n No activity yet. Agent activity will appear here in real-time.\n </div>\n ) : (\n <div className=\"divide-y divide-[#1a1a1a]\">\n {activities.map(evt => (\n <div key={evt.id} className=\"px-4 py-2.5 hover:bg-[#111]/50 transition\">\n <p className=\"text-sm truncate\">{(evt.data?.activity as string) || \"Working...\"}</p>\n <div className=\"flex items-center gap-2 text-[10px] text-[#555] mt-0.5\">\n <span className=\"text-[#666]\">{agentNameMap.get(evt.agent_id) || evt.agent_id}</span>\n <span className=\"text-[#444]\">&middot;</span>\n <span>{timeAgo(evt.timestamp)}</span>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Right: Tasks (3/8) */}\n <div className=\"flex-[3] flex flex-col overflow-hidden\">\n <div className=\"px-4 py-2.5 border-b border-[#1a1a1a] flex items-center justify-between shrink-0\">\n <h3 className=\"text-xs font-semibold text-[#666] uppercase tracking-wider\">Tasks</h3>\n {onNavigate && (\n <button onClick={() => onNavigate(\"tasks\")} className=\"text-xs text-[#3b82f6] hover:text-[#60a5fa]\">\n View All\n </button>\n )}\n </div>\n <div className=\"flex-1 overflow-auto px-3 py-3\">\n {tasks.length === 0 ? (\n <p className=\"text-sm text-[#555] px-2 py-4 text-center\">No tasks yet</p>\n ) : (\n <div className=\"space-y-2.5\">\n {tasks.map(task => (\n <TaskCard key={`${task.agentId}-${task.id}`} task={task} />\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n// --- Agent Row ---\n\nfunction AgentRow({ agent, selected, onSelect }: {\n agent: Agent;\n selected: boolean;\n onSelect: () => void;\n}) {\n const { isActive, label } = useAgentActivity(agent.id);\n const isRunning = agent.status === \"running\";\n\n return (\n <button\n onClick={onSelect}\n className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition ${\n selected\n ? \"bg-[#f97316]/10 border border-[#f97316]/30\"\n : \"hover:bg-[#1a1a1a] border border-transparent\"\n }`}\n >\n <span\n className={`w-2.5 h-2.5 rounded-full shrink-0 ${\n isRunning && isActive\n ? \"bg-green-400 animate-pulse\"\n : isRunning\n ? \"bg-[#3b82f6]\"\n : \"bg-[#444]\"\n }`}\n />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className={`text-sm font-medium truncate ${isRunning ? \"\" : \"text-[#666]\"}`}>\n {agent.name}\n </span>\n <span className=\"text-[10px] text-[#555] shrink-0\">{agent.provider}</span>\n </div>\n {isActive && label ? (\n <p className=\"text-[11px] text-green-400 truncate\">{label}</p>\n ) : (\n <p className={`text-[11px] ${isRunning ? \"text-[#555]\" : \"text-[#444]\"}`}>\n {isRunning ? \"idle\" : \"stopped\"}\n </p>\n )}\n </div>\n </button>\n );\n}\n\n// --- Inline Command ---\n\nfunction InlineCommand({ agent }: { agent: Agent | null }) {\n const { authFetch } = useAuth();\n const [command, setCommand] = useState(\"\");\n const [sending, setSending] = useState(false);\n const [toast, setToast] = useState<string | null>(null);\n\n useEffect(() => {\n setCommand(\"\");\n setToast(null);\n }, [agent?.id]);\n\n if (!agent) return null;\n\n const isRunning = agent.status === \"running\";\n\n const handleSend = async () => {\n if (!command.trim() || sending) return;\n if (!isRunning) {\n setToast(\"Agent is not running\");\n setTimeout(() => setToast(null), 3000);\n return;\n }\n setSending(true);\n try {\n const res = await authFetch(`/api/agents/${agent.id}/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ message: command, agent_id: agent.id }),\n });\n if (res.ok) {\n setToast(\"Sent\");\n setCommand(\"\");\n } else {\n const data = await res.json().catch(() => ({}));\n setToast(data.error || \"Failed\");\n }\n } catch {\n setToast(\"Failed to send\");\n } finally {\n setSending(false);\n setTimeout(() => setToast(null), 3000);\n }\n };\n\n return (\n <div className=\"mt-2 bg-[#0a0a0a] border border-[#1a1a1a] rounded-lg p-2.5\">\n <div className=\"flex items-center justify-between mb-1.5\">\n <span className=\"text-[10px] text-[#666]\">\n Send to <span className=\"text-[#888]\">{agent.name}</span>\n </span>\n {toast && (\n <span className={`text-[10px] px-1.5 py-0.5 rounded ${\n toast === \"Sent\" ? \"bg-green-500/10 text-green-400\" : \"bg-red-500/10 text-red-400\"\n }`}>{toast}</span>\n )}\n </div>\n <div className=\"flex gap-1.5\">\n <input\n type=\"text\"\n value={command}\n onChange={e => setCommand(e.target.value)}\n onKeyDown={e => e.key === \"Enter\" && handleSend()}\n placeholder={isRunning ? \"Command...\" : \"Not running\"}\n disabled={sending || !isRunning}\n autoFocus\n className=\"flex-1 bg-[#111] border border-[#1a1a1a] rounded px-2 py-1.5 text-xs focus:outline-none focus:border-[#f97316] placeholder-[#444] disabled:opacity-50\"\n />\n <button\n onClick={handleSend}\n disabled={sending || !command.trim() || !isRunning}\n className=\"px-2.5 py-1.5 bg-[#f97316]/20 text-[#f97316] rounded text-xs font-medium hover:bg-[#f97316]/30 transition disabled:opacity-30\"\n >\n {sending ? \"...\" : \"Send\"}\n </button>\n </div>\n </div>\n );\n}\n\n// --- Task Card (matches TasksPage style) ---\n\nconst taskStatusColors: 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\nconst TASK_DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\nfunction TaskCard({ task }: { task: Task }) {\n return (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-3 hover:border-[#333] transition\">\n <div className=\"flex items-start justify-between mb-1.5\">\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"text-sm font-medium truncate\">{task.title}</h4>\n <p className=\"text-xs text-[#666]\">{task.agentName}</p>\n </div>\n <span className={`px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 ml-2 ${taskStatusColors[task.status] || taskStatusColors.pending}`}>\n {task.status}\n </span>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-[#555]\">\n <span className=\"flex items-center gap-1\">\n {task.type === \"recurring\"\n ? <RecurringIcon className=\"w-3 h-3\" />\n : task.execute_at\n ? <ScheduledIcon className=\"w-3 h-3\" />\n : <TaskOnceIcon className=\"w-3 h-3\" />\n }\n {task.type === \"recurring\" && task.recurrence ? formatCronShort(task.recurrence) : task.type}\n </span>\n {task.next_run && (\n <span className=\"text-[#f97316]\">{formatTaskRelative(task.next_run)}</span>\n )}\n {!task.next_run && task.execute_at && (\n <span className=\"text-[#f97316]\">{formatTaskRelative(task.execute_at)}</span>\n )}\n </div>\n </div>\n );\n}\n\n// --- Helpers ---\n\nfunction formatCronShort(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 if (minute.startsWith(\"*/\") && hour === \"*\" && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n const n = parseInt(minute.slice(2));\n return n === 1 ? \"Every min\" : `Every ${n}min`;\n }\n if (minute !== \"*\" && !minute.includes(\"/\") && hour === \"*\" && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n return \"Hourly\";\n }\n if (hour.startsWith(\"*/\") && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n const n = parseInt(hour.slice(2));\n return n === 1 ? \"Hourly\" : `Every ${n}h`;\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 if (dayOfWeek === \"*\") return `Daily ${timeStr}`;\n const days = dayOfWeek.split(\",\").map(d => TASK_DAY_NAMES[parseInt(d.trim())] || d);\n if (days.length === 1) return `${days[0]} ${timeStr}`;\n return `${days.join(\", \")} ${timeStr}`;\n }\n return cron;\n } catch {\n return cron;\n }\n}\n\nfunction formatTaskRelative(dateStr: string): string {\n const date = new Date(dateStr);\n const now = new Date();\n const diffMs = date.getTime() - now.getTime();\n const isFuture = diffMs > 0;\n const absDiffMs = Math.abs(diffMs);\n const minutes = Math.floor(absDiffMs / 60000);\n const hours = Math.floor(absDiffMs / 3600000);\n const timeStr = date.toLocaleTimeString([], { hour: \"numeric\", minute: \"2-digit\" });\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\n if (isToday) {\n if (minutes < 1) return \"now\";\n if (minutes < 60) return isFuture ? `in ${minutes}m` : `${minutes}m ago`;\n return isFuture ? `in ${hours}h (${timeStr})` : `${hours}h ago`;\n }\n if (isTomorrow) return `Tomorrow ${timeStr}`;\n return `${TASK_DAY_NAMES[date.getDay()]} ${timeStr}`;\n}\n\nfunction timeAgo(timestamp: string): string {\n const seconds = Math.floor((Date.now() - new Date(timestamp).getTime()) / 1000);\n if (seconds < 5) return \"just now\";\n if (seconds < 60) return `${seconds}s ago`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "A710C5DDE644C40564756E2164756E21",
9
+ "names": []
10
+ }