@capagents/forgeqe 2.4.1 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/forgeqe.js +886 -886
- package/dist/web/assets/ApiTests-B-0nk720.js +2 -0
- package/dist/web/assets/Chat-Be6J6POH.js +3 -0
- package/dist/web/assets/{Data-C-xQyf3P.js → Data-BtcD7_T2.js} +4 -4
- package/dist/web/assets/Features-DHIGL43K.js +1 -0
- package/dist/web/assets/Jobs-C-cEyrrH.js +3 -0
- package/dist/web/assets/Quality-C6hKykoO.js +1 -0
- package/dist/web/assets/Record-B5395d_b.js +1 -0
- package/dist/web/assets/Regression-BS5g4T3v.js +2 -0
- package/dist/web/assets/Reports-CHqfhNR8.js +2 -0
- package/dist/web/assets/Response-P2oku3_B.js +8 -0
- package/dist/web/assets/Runs-DPmd5QPL.js +2 -0
- package/dist/web/assets/chevron-right-Cwpv0kJi.js +1 -0
- package/dist/web/assets/circle-dashed-COka5oNi.js +1 -0
- package/dist/web/assets/external-link-B9T-hxHX.js +1 -0
- package/dist/web/assets/file-chart-column-increasing-Ch7H145u.js +1 -0
- package/dist/web/assets/filters-C5e4Y0To.js +1 -0
- package/dist/web/assets/index-BI_5kNwE.css +2 -0
- package/dist/web/assets/index-KUNDUjo0.js +26 -0
- package/dist/web/assets/{markdown-B1Rz6VFK.js → markdown-DclrGj2e.js} +7 -7
- package/dist/web/assets/rotate-ccw-BizUsxuR.js +1 -0
- package/dist/web/assets/sticky-note-CFIxnO7K.js +1 -0
- package/dist/web/assets/terminal-BnhGgg6d.js +1 -0
- package/dist/web/assets/trash-CtWVl2Xk.js +1 -0
- package/dist/web/assets/trending-up-BnzWZEhg.js +1 -0
- package/dist/web/index.html +2 -3
- package/package.json +1 -1
- package/dist/web/assets/ApiTests-CoFraMwL.js +0 -2
- package/dist/web/assets/Chat-BRCv-waj.js +0 -3
- package/dist/web/assets/Features-VtoyECeO.js +0 -1
- package/dist/web/assets/Jobs-8t_bMM0e.js +0 -3
- package/dist/web/assets/Quality-DS_r7p5G.js +0 -1
- package/dist/web/assets/Record-uvTYm_xC.js +0 -1
- package/dist/web/assets/Regression-C09uOUEu.js +0 -2
- package/dist/web/assets/Reports-CZTOMDhT.js +0 -3
- package/dist/web/assets/Response-CgGBxdB7.js +0 -8
- package/dist/web/assets/Runs-B29dpes6.js +0 -2
- package/dist/web/assets/circle-dashed-zjN_W6rR.js +0 -1
- package/dist/web/assets/external-link-D2pA4PJ0.js +0 -1
- package/dist/web/assets/file-chart-column-increasing-FSDL2nUM.js +0 -1
- package/dist/web/assets/index-CJr3aeU5.css +0 -2
- package/dist/web/assets/index-DuYynJ55.js +0 -24
- package/dist/web/assets/rotate-ccw-dA-H7K_B.js +0 -1
- package/dist/web/assets/status-xNQO8J6U.js +0 -3
- package/dist/web/assets/sticky-note-BuQrlbjE.js +0 -1
- package/dist/web/assets/terminal-ib42D5b6.js +0 -1
- package/dist/web/assets/trash-540pMBsR.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./index-KUNDUjo0.js";var t={name:`arrow-left`,size:24,node:[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]};t.node;var n=e(t),r={name:`rotate-ccw`,size:24,node:[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]};r.node;var i=e(r);export{n,i as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./index-KUNDUjo0.js";var t={name:`sticky-note`,size:24,node:[[`path`,{d:`M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z`,key:`1dfntj`}],[`path`,{d:`M15 3v5a1 1 0 0 0 1 1h5`,key:`6s6qgf`}]]};t.node;var n=e(t);export{n as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./index-KUNDUjo0.js";var t={name:`terminal`,size:24,node:[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]};t.node;var n=e(t);export{n as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./index-KUNDUjo0.js";var t={name:`trash`,size:24,node:[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]],aliases:[`trash-2`]};t.node;var n=e(t);export{n as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e}from"./index-KUNDUjo0.js";var t={name:`trending-down`,size:24,node:[[`path`,{d:`M16 17h6v-6`,key:`t6n2it`}],[`path`,{d:`m22 17-8.5-8.5-5 5L2 7`,key:`x473p`}]]};t.node;var n=e(t),r={name:`trending-up`,size:24,node:[[`path`,{d:`M16 7h6v6`,key:`box55l`}],[`path`,{d:`m22 7-8.5 8.5-5-5L2 17`,key:`1t1m79`}]]};r.node;var i=e(r);export{n,i as t};
|
package/dist/web/index.html
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="referrer" content="no-referrer" />
|
|
7
7
|
<title>ForgeQE</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-CJr3aeU5.css">
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-KUNDUjo0.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BI_5kNwE.css">
|
|
11
10
|
</head>
|
|
12
11
|
<body>
|
|
13
12
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capagents/forgeqe",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "ForgeQE: a browser agent CLI that runs goals and test cases in local Chrome or Chromium, or BrowserStack and TestMu AI/LambdaTest when configured, and turns passing runs into tests in your repo",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{$ as e,I as t,J as n,K as r,Kt as i,L as a,N as o,P as s,Q as c,R as l,Vt as u,Y as d,Z as f,fn as p,it as m,ln as h,nt as g,p as _,pt as v,q as y,qt as b,r as x,t as S}from"./status-xNQO8J6U.js";import"./markdown-B1Rz6VFK.js";import{t as C}from"./file-chart-column-increasing-FSDL2nUM.js";import{A as w,S as T,f as E,p as D}from"./index-DuYynJ55.js";var O={name:`braces`,size:24,node:[[`path`,{d:`M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1`,key:`ezmyqa`}],[`path`,{d:`M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1`,key:`e1hn23`}]],aliases:[`curly-braces`]};O.node;var k=u(O),A={name:`link-2`,size:24,node:[[`path`,{d:`M9 17H7A5 5 0 0 1 7 7h2`,key:`8i5ue5`}],[`path`,{d:`M15 7h2a5 5 0 1 1 0 10h-2`,key:`1b9ql8`}],[`line`,{x1:`8`,x2:`16`,y1:`12`,y2:`12`,key:`1jonct`}]]};A.node;var j=u(A),M=p(h(),1),N=f(),P={passed:`pass`,failed:`fail`,error:`fail`,skipped:`neutral`},F={GET:`text-pass`,POST:`text-accent`,PUT:`text-warn`,PATCH:`text-warn`,DELETE:`text-fail`},I={run:`a browser run's calls`,openapi:`OpenAPI`,swagger:`Swagger`,wsdl:`WSDL`,graphql:`GraphQL`,proto:`.proto`,case:`a test case`,text:`a description`},L=e=>new Date(e).toLocaleString([],{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`}),R=e=>e?e.failed||e.error?`fail`:e.passed?`pass`:`neutral`:`neutral`;function z({job:e,onStop:t}){let n=(0,M.useRef)(null);(0,M.useEffect)(()=>{n.current&&(n.current.scrollTop=n.current.scrollHeight)},[e.lines.length]);let[r,i]={contracts:[`Making contracts`,`Made contracts`],run:[`Running the contracts`,`Ran the contracts`],scenarios:[`Making scenarios`,`Made scenarios`],"run-scenarios":[`Running the scenarios`,`Ran the scenarios`]}[e.kind]??[`Working`,`Done`],a=(e.kind===`run`||e.kind===`run-scenarios`)&&e.exitCode===1;return(0,N.jsxs)(`section`,{"aria-label":e.running?r:i,className:`flex flex-col gap-2 rounded-[14px] border border-line-soft p-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(`span`,{className:`flex-1 font-medium`,children:e.running?r:i}),(0,N.jsx)(S,{orb:e.kind===`contracts`?`handing`:e.kind===`scenarios`?`writing`:`working`,tone:e.running?`running`:e.exitCode===0?`pass`:a?`warn`:`fail`,children:e.running?`Working`:e.exitCode===0?`Done`:a?`Some failed`:`Did not finish`}),e.running&&(0,N.jsxs)(d,{onClick:t,className:`border-fail text-fail hover:bg-fail-soft`,children:[(0,N.jsx)(m,{size:14,fill:`currentColor`,"aria-hidden":`true`}),`Stop`]})]}),(0,N.jsx)(`code`,{className:`font-mono text-[12px] text-muted [overflow-wrap:anywhere]`,children:e.command}),(0,N.jsxs)(`details`,{open:e.running,children:[(0,N.jsxs)(`summary`,{className:`cursor-pointer text-sm text-muted`,children:[`Output (`,e.lines.length,` lines)`]}),(0,N.jsx)(`pre`,{ref:n,className:`mt-2 max-h-[300px] overflow-auto rounded-[10px] bg-surface-muted p-3 font-mono text-[12px] leading-relaxed whitespace-pre-wrap text-ink-2`,children:e.lines.join(`
|
|
2
|
-
`)||`Starting…`})]})]})}var B=({m:e})=>(0,N.jsx)(`span`,{className:c(`w-[58px] flex-none font-mono text-[12px] font-semibold`,F[e.toUpperCase()]||`text-ink-2`),children:e.toUpperCase()});function V({c:e,r:t}){let n=Array.isArray(e.expect.status)?e.expect.status.join(` or `):e.expect.status;return(0,N.jsxs)(`li`,{className:`flex flex-col gap-1 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2`,children:[(0,N.jsx)(B,{m:e.method}),(0,N.jsx)(`span`,{className:`min-w-0 flex-1 font-mono text-[13px] [overflow-wrap:anywhere]`,children:e.protocol===`rest`?e.path:e.name}),e.writes&&(0,N.jsx)(S,{tone:`warn`,children:`Changes data`}),e.needsData?.length?(0,N.jsxs)(S,{tone:`neutral`,icon:!1,children:[`Needs real `,e.needsData.join(`, `)]}):null,t&&(0,N.jsx)(S,{tone:P[t.status],children:t.status===`skipped`?`Skipped`:t.httpStatus?`${t.httpStatus}`:t.status})]}),(0,N.jsx)(`span`,{className:`pl-[66px] text-[12px] text-muted`,children:[n?`expects ${n}`:``,e.expect.contentType,e.expect.keyFields?.length?`${e.expect.keyFields.length} key field${e.expect.keyFields.length===1?``:`s`}`:``,e.auth?`${e.auth.type} auth`:``].filter(Boolean).join(` · `)}),t&&t.status!==`passed`&&(t.reason||t.checks.some(e=>!e.ok))&&(0,N.jsx)(`span`,{className:c(`pl-[66px] text-[12px] [overflow-wrap:anywhere]`,t.status===`skipped`?`text-muted`:`text-fail`),children:[t.reason,...t.checks.filter(e=>!e.ok).map(e=>`${e.name}${e.detail?`: ${e.detail}`:``}`)].filter(Boolean).join(` · `)})]})}function H({s:e,r:t}){let[n,r]=(0,M.useState)(!1);return(0,N.jsxs)(`li`,{className:`border-t border-line-soft first:border-t-0`,children:[(0,N.jsxs)(`button`,{type:`button`,"aria-expanded":n,onClick:()=>r(!n),className:`flex min-h-[52px] w-full cursor-pointer items-center gap-3 border-0 bg-transparent px-1 py-2 text-left text-ink hover:bg-surface-muted`,children:[(0,N.jsx)(E,{size:16,"aria-hidden":`true`,className:`flex-none text-muted`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`text-sm [overflow-wrap:anywhere]`,children:e.name}),(0,N.jsxs)(`span`,{className:`truncate text-[12px] text-muted`,children:[e.kind,` · `,e.steps.length,` step`,e.steps.length===1?``:`s`,e.cleanup?.length?` · ${e.cleanup.length} cleanup`:``,e.caseId?` · ${e.caseId}`:``]})]}),e.writes&&(0,N.jsx)(S,{tone:`warn`,children:`Changes data`}),t&&(0,N.jsx)(S,{tone:P[t.status],children:t.status.charAt(0).toUpperCase()+t.status.slice(1)})]}),n&&(0,N.jsxs)(`ol`,{className:`m-0 mb-3 ml-8 flex list-none flex-col gap-1 border-l border-line pl-3 text-sm`,children:[e.steps.map((e,n)=>{let r=t?.steps[n];return(0,N.jsxs)(`li`,{className:`flex flex-col`,children:[(0,N.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2`,children:[(0,N.jsx)(B,{m:e.method}),(0,N.jsx)(`span`,{className:`min-w-0 flex-1 font-mono text-[12px] [overflow-wrap:anywhere]`,children:e.path}),r&&(0,N.jsx)(S,{tone:P[r.status],children:r.httpStatus?String(r.httpStatus):r.status})]}),(0,N.jsxs)(`span`,{className:`pl-[66px] text-[12px] text-muted`,children:[e.name,e.save&&Object.keys(e.save).length?` · keeps ${Object.keys(e.save).join(`, `)}`:``,e.noAuth?` · without credentials`:``]}),r&&r.checks.some(e=>!e.ok)&&(0,N.jsx)(`span`,{className:`pl-[66px] text-[12px] text-fail`,children:r.checks.filter(e=>!e.ok).map(e=>`${e.name}${e.detail?`: ${e.detail}`:``}`).join(` · `)})]},n)}),e.cleanup?.map((e,t)=>(0,N.jsxs)(`li`,{className:`flex items-center gap-2 text-muted`,children:[(0,N.jsx)(B,{m:e.method}),(0,N.jsx)(`span`,{className:`font-mono text-[12px]`,children:e.path}),(0,N.jsx)(`span`,{className:`text-[12px]`,children:`cleanup`})]},`c${t}`)),t?.reason&&(0,N.jsx)(`li`,{className:`text-[12px] text-fail [overflow-wrap:anywhere]`,children:t.reason})]})]})}function U({what:e,writes:t,defaultUrl:n,onRun:i,onCancel:a,needsData:s}){let[c,l]=(0,M.useState)(n),[u,f]=(0,M.useState)(!1),[p,m]=(0,M.useState)(!1);return(0,N.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-[12px] border border-accent-line bg-accent-soft p-4`,children:[(0,N.jsx)(`span`,{className:`font-medium`,children:e}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1.5 text-sm`,children:[`Against`,(0,N.jsx)(o,{value:c,spellCheck:!1,placeholder:`https://qa.example.com/api`,onChange:e=>l(e.target.value),className:`max-w-[480px] bg-bg`})]}),t>0&&(0,N.jsxs)(`span`,{className:`flex items-start gap-3 text-sm`,children:[(0,N.jsx)(r,{checked:u,onChange:f,label:`Also run the calls that change data`}),(0,N.jsxs)(`span`,{className:`flex flex-col`,children:[`Also run the `,t,` call`,t===1?``:`s`,` that change data`,(0,N.jsx)(`span`,{className:`text-[13px] text-warn`,children:`Only on a test environment: they create, change or delete data there.`})]})]}),s?(0,N.jsxs)(`span`,{className:`flex items-center gap-3 text-sm`,children:[(0,N.jsx)(r,{checked:p,onChange:m,label:`Also run calls with made-up values`}),`Also run the `,s,` call`,s===1?``:`s`,` whose values were made up`]}):null,(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsxs)(d,{variant:`primary`,onClick:()=>i({...c.trim()?{baseUrl:c.trim()}:{},allowWrites:u,includeNeedsData:p}),children:[(0,N.jsx)(v,{size:16,"aria-hidden":`true`}),`Run`]}),(0,N.jsx)(d,{onClick:a,children:`Don't run`})]})]})}function W({open:n,onClose:i,view:a,set:l,onMake:u,busy:f}){let[p,m]=(0,M.useState)(`spec`),[h,g]=(0,M.useState)(``),[_,v]=(0,M.useState)(``),[y,b]=(0,M.useState)(``),[x,S]=(0,M.useState)(!0);(0,M.useEffect)(()=>{n&&(m(l.source.kind===`run`?`run`:`spec`),g(l.source.kind===`run`?``:a.runs[0]?.id??``))},[n,l.source.kind,a.runs]);let C=(e,t,n)=>(0,N.jsxs)(`label`,{className:c(`flex cursor-pointer items-start gap-3 rounded-[12px] border px-3 py-2.5`,p===e?`border-accent bg-accent-soft`:`border-line-soft hover:bg-surface-muted`),children:[(0,N.jsx)(`input`,{type:`radio`,name:`sc-from`,checked:p===e,onChange:()=>m(e),className:`mt-1 size-4 accent-accent`}),(0,N.jsxs)(`span`,{className:`flex flex-col`,children:[(0,N.jsx)(`span`,{className:`text-sm font-medium`,children:t}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:n})]})]});return(0,N.jsx)(t,{open:n,onClose:i,title:`Make scenarios`,description:`API calls in order, where later calls use values earlier answers gave, added to ${l.name}. Nothing runs until you run them.`,footer:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(d,{onClick:i,children:`Cancel`}),(0,N.jsx)(d,{variant:`primary`,disabled:f||p===`cases`&&!_.trim()||p===`text`&&!y.trim(),onClick:()=>u({from:p,...p===`run`&&h?{run:h}:{},...p===`cases`?{cases:_}:{},...p===`text`?{text:y}:{},...p===`spec`?{negative:x}:{}}),children:`Make scenarios`})]}),children:(0,N.jsxs)(`div`,{className:`flex flex-col gap-2 pt-3`,children:[C(`spec`,`From the API description`,`Each resource's lifecycle, browsing, the description's links, and negative cases (no model)`),p===`spec`&&(0,N.jsxs)(`span`,{className:`flex items-center gap-2 pl-10 text-sm`,children:[(0,N.jsx)(r,{checked:x,onChange:S,label:`Negative cases`}),` Negative cases: an id that does not exist, no credentials, an empty body`]}),C(`run`,`From a browser run`,`The calls the application made, in order, with the values passed on (no model)`),p===`run`&&(0,N.jsxs)(s,{"aria-label":`Browser run`,value:h,onChange:e=>g(e.target.value),className:`ml-10 max-w-[440px]`,children:[(0,N.jsx)(`option`,{value:``,children:`The latest run`}),a.runs.map(t=>(0,N.jsxs)(`option`,{value:t.id,children:[t.goal,` · `,e(t.calls,`call`),` · `,L(t.at)]},t.id))]}),C(`cases`,`From test cases`,`One scenario per case, planned by the model against the set's operations`),p===`cases`&&(0,N.jsx)(o,{"aria-label":`Test cases`,value:_,spellCheck:!1,placeholder:`ado:2238, jira:SHOP-12`,onChange:e=>v(e.target.value),className:`ml-10 max-w-[440px]`}),C(`text`,`From a description`,`In plain words, planned by the model; a step no operation does is listed, never invented`),p===`text`&&(0,N.jsx)(o,{"aria-label":`The scenario`,value:y,maxLength:1e3,placeholder:`Create a user, log in, add two items, check out, the total is the sum`,onChange:e=>b(e.target.value),className:`ml-10`})]})})}function G({open:n,onClose:r,view:i,onMake:a,busy:c}){let[l,u]=(0,M.useState)(`spec`),[f,p]=(0,M.useState)(``),[m,h]=(0,M.useState)(``),[g,_]=(0,M.useState)(``),[v,y]=(0,M.useState)(``);return(0,M.useEffect)(()=>{n&&(p(i.specs[0]??``),h(``),_(``),y(i.baseUrl??``),u(i.specs.length||!i.runs.length?`spec`:`run`))},[n,i]),(0,N.jsx)(t,{open:n,onClose:r,title:`New contract set`,description:`One contract per operation: an example call and what its answer must have (status, content type, schema, key fields). Making them runs nothing.`,footer:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(d,{onClick:r,children:`Cancel`}),(0,N.jsx)(d,{variant:`primary`,disabled:c||l===`spec`&&!f.trim(),onClick:()=>a({from:l,...l===`spec`?{spec:f.trim()}:m?{run:m}:{},...g.trim()?{name:g.trim()}:{},...v.trim()?{baseUrl:v.trim()}:{}}),children:`Make contracts`})]}),children:(0,N.jsxs)(`div`,{className:`flex flex-col gap-4 pt-3`,children:[(0,N.jsxs)(`fieldset`,{className:`m-0 flex flex-col gap-2 border-0 p-0`,children:[(0,N.jsx)(`legend`,{className:`mb-1.5 text-sm font-medium`,children:`From`}),(0,N.jsxs)(`label`,{className:`flex min-h-9 cursor-pointer items-center gap-2 text-sm`,children:[(0,N.jsx)(`input`,{type:`radio`,name:`set-from`,checked:l===`spec`,onChange:()=>u(`spec`),className:`size-4 accent-accent`}),`An API description: OpenAPI or Swagger, WSDL, GraphQL, .proto, or grpc://`]}),l===`spec`&&(0,N.jsxs)(`div`,{className:`flex flex-col gap-1.5 pl-6`,children:[(0,N.jsx)(o,{"aria-label":`API description`,value:f,spellCheck:!1,list:`spec-files`,placeholder:`https://shop.test/openapi.json, or a file in the project`,onChange:e=>p(e.target.value)}),(0,N.jsx)(`datalist`,{id:`spec-files`,children:i.specs.map(e=>(0,N.jsx)(`option`,{value:e},e))}),i.specs.length>0&&(0,N.jsxs)(`span`,{className:`text-[13px] text-muted`,children:[`In this project: `,i.specs.slice(0,6).join(`, `)]})]}),(0,N.jsxs)(`label`,{className:`flex min-h-9 cursor-pointer items-center gap-2 text-sm`,children:[(0,N.jsx)(`input`,{type:`radio`,name:`set-from`,checked:l===`run`,onChange:()=>u(`run`),className:`size-4 accent-accent`}),`The calls a browser run saw the application make`]}),l===`run`&&(0,N.jsxs)(s,{"aria-label":`Browser run`,value:m,onChange:e=>h(e.target.value),className:`ml-6 max-w-[440px]`,children:[(0,N.jsx)(`option`,{value:``,children:`The latest run`}),i.runs.map(t=>(0,N.jsxs)(`option`,{value:t.id,children:[t.goal,` · `,e(t.calls,`call`),` · `,L(t.at)]},t.id))]})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1.5 text-sm font-medium`,children:[`Name`,(0,N.jsx)(o,{value:g,maxLength:120,placeholder:`Petstore`,onChange:e=>_(e.target.value)})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1.5 text-sm font-medium`,children:[`Base URL`,(0,N.jsx)(o,{value:v,spellCheck:!1,placeholder:`https://qa.shop.test/api`,onChange:e=>y(e.target.value)}),(0,N.jsxs)(`span`,{className:`text-[13px] font-normal text-muted`,children:[`Where the contracts run when not where they were recorded or described.`,i.headers.length?` Each call sends ${i.headers.join(`, `)} from api.headers in forgeqe.yaml.`:` Credentials go in api.headers in forgeqe.yaml, as references to environment variables.`]})]})]})})}function K({id:e,view:t,busy:n,act:r,version:o}){let[s,c]=(0,M.useState)(null),[u,f]=(0,M.useState)(``),[p,m]=(0,M.useState)(null),[h,g]=(0,M.useState)(!1),[y,x]=(0,M.useState)(``);(0,M.useEffect)(()=>{let t=!1;return i.set(e).then(e=>!t&&(c(e),f(``)),e=>!t&&f(e.message)),()=>{t=!0}},[e,o]),(0,M.useEffect)(()=>m(null),[e]);let O=(0,M.useMemo)(()=>new Map((s?.last.contracts?.results??[]).map(e=>[e.id,e])),[s]),A=(0,M.useMemo)(()=>new Map((s?.last.scenarios?.results??[]).map(e=>[e.id,e])),[s]);if(u)return(0,N.jsx)(`p`,{className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:u});if(!s)return(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Loading…`});let j=s.contracts.filter(e=>e.writes).length,P=s.contracts.filter(e=>e.needsData?.length).length,F=s.scenarios??[],z=s.last.contracts,B=s.last.scenarios,G=t.baseUrl||s.baseUrl||``,K=async e=>{try{let{id:t}=await b.start(`Write the API contracts${e?` and scenarios`:``} of set ${s.id} as tests in the repository: call write_api_tests with set_id ${s.id}${e?` and scenarios ["all"]`:``}. Show me the plan before you write.`,{});location.hash=l(`chats`,t)}catch(e){x(e.message)}};return(0,N.jsxs)(`section`,{"aria-labelledby":`set-h`,className:`flex min-w-0 flex-1 flex-col gap-6`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-start gap-3`,children:[(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-1`,children:[(0,N.jsx)(`h2`,{id:`set-h`,className:`m-0 text-[22px] font-semibold tracking-[-0.01em] [overflow-wrap:anywhere]`,children:s.name}),(0,N.jsxs)(`span`,{className:`text-sm text-muted [overflow-wrap:anywhere]`,children:[`From `,I[s.source.kind]||s.source.kind,` `,(0,N.jsx)(`span`,{className:`font-mono text-[12px]`,children:s.source.ref}),` · `,L(s.createdAt)]}),s.baseUrl&&(0,N.jsx)(`span`,{className:`font-mono text-[12px] text-muted [overflow-wrap:anywhere]`,children:s.baseUrl})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsxs)(d,{variant:`primary`,disabled:n||!s.contracts.length,onClick:()=>m(`contracts`),children:[(0,N.jsx)(v,{size:16,"aria-hidden":`true`}),`Run contracts`]}),(0,N.jsxs)(d,{disabled:n||!F.length,onClick:()=>m(`scenarios`),children:[(0,N.jsx)(v,{size:16,"aria-hidden":`true`}),`Run scenarios`]}),(0,N.jsxs)(d,{disabled:n,onClick:()=>g(!0),children:[(0,N.jsx)(T,{size:16,"aria-hidden":`true`}),`Make scenarios`]})]})]}),p===`contracts`&&(0,N.jsx)(U,{what:`Run ${s.contracts.length} contract${s.contracts.length===1?``:`s`}`,writes:j,needsData:P,defaultUrl:G,onCancel:()=>m(null),onRun:e=>{m(null),r(()=>i.run(s.id,e))}}),p===`scenarios`&&(0,N.jsx)(U,{what:`Run ${F.length} scenario${F.length===1?``:`s`}`,writes:F.filter(e=>e.writes).length,defaultUrl:G,onCancel:()=>m(null),onRun:e=>{m(null),r(()=>i.runScenarios(s.id,{...e.baseUrl?{baseUrl:e.baseUrl}:{},allowWrites:e.allowWrites}))}}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,N.jsx)(_,{icon:k,label:`Contracts`,value:String(s.contracts.length),note:[j?`${j} change data`:``,P?`${P} need real values`:``].filter(Boolean).join(` · `)||void 0}),(0,N.jsx)(_,{icon:E,label:`Scenarios`,value:String(F.length)}),(0,N.jsx)(_,{icon:w,label:`Contracts run`,value:z?`${z.counts.passed}/${z.counts.passed+z.counts.failed+z.counts.error}`:`–`,note:z?`passed · ${L(z.at)}`:`Not run yet`}),(0,N.jsx)(_,{icon:w,label:`Scenarios run`,value:B?`${B.counts.passed}/${B.counts.passed+B.counts.failed+B.counts.error}`:`–`,note:B?`passed · ${L(B.at)}`:`Not run yet`})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[z?.report&&(0,N.jsxs)(d,{onClick:async()=>x(await a(z.report)),children:[(0,N.jsx)(C,{size:16,"aria-hidden":`true`}),`Contracts report`]}),B?.report&&(0,N.jsxs)(d,{onClick:async()=>x(await a(B.report)),children:[(0,N.jsx)(C,{size:16,"aria-hidden":`true`}),`Scenarios report`]}),(0,N.jsxs)(d,{variant:`ghost`,onClick:()=>void K(F.length>0),children:[(0,N.jsx)(D,{size:16,"aria-hidden":`true`}),`Write them as tests`]}),y&&(0,N.jsx)(`span`,{className:`text-[13px] text-fail`,children:y})]}),(0,N.jsxs)(`section`,{className:`flex flex-col gap-2`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,N.jsxs)(`h3`,{className:`m-0 flex-1 text-base font-semibold`,children:[`Contracts (`,s.contracts.length,`)`]}),z&&(0,N.jsxs)(S,{tone:R(z.counts),children:[z.counts.passed,` passed · `,z.counts.failed+z.counts.error,` failed · `,z.counts.skipped,` skipped`]})]}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:s.contracts.slice(0,300).map(e=>(0,N.jsx)(V,{c:e,r:O.get(e.id)},e.id))}),s.skipped?.length?(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[`Left out: `,s.skipped.slice(0,10).join(`; `)]}):null]}),(0,N.jsxs)(`section`,{className:`flex flex-col gap-2`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,N.jsxs)(`h3`,{className:`m-0 flex-1 text-base font-semibold`,children:[`Scenarios (`,F.length,`)`]}),B&&(0,N.jsxs)(S,{tone:R(B.counts),children:[B.counts.passed,` passed · `,B.counts.failed+B.counts.error,` failed · `,B.counts.skipped,` skipped`]})]}),F.length?(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:F.map(e=>(0,N.jsx)(H,{s:e,r:A.get(e.id)},e.id))}):(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`None yet: Make scenarios chains the calls end to end, from the description, a browser run, test cases, or a few words.`})]}),(0,N.jsx)(W,{open:h,onClose:()=>g(!1),view:t,set:s,busy:n,onMake:e=>{g(!1),r(()=>i.scenarios(s.id,e))}})]})}function q({sub:t}){let[r,a]=(0,M.useState)(null),[o,s]=(0,M.useState)(``),[u,f]=(0,M.useState)(!1),[p,m]=(0,M.useState)(!1),h=(0,M.useCallback)(()=>{i.view().then(e=>{a(e),s(``)},e=>s(e.message))},[]);(0,M.useEffect)(h,[h]);let _=!!r?.job?.running;(0,M.useEffect)(()=>{if(!_)return;let e=setInterval(h,1500);return()=>clearInterval(e)},[_,h]);let v=async e=>{f(!0),s(``);try{await e(),h()}catch(e){s(e.message)}finally{f(!1)}},b=t?decodeURIComponent(t):``,S=r?.sets.find(e=>e.id===b)||r?.sets[0],C=`${r?.job?.endedAt??``}|${S?.at??``}`;return(0,N.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,N.jsx)(x,{}),(0,N.jsxs)(`main`,{className:`@container mx-auto box-border flex w-full max-w-[1180px] flex-auto flex-col gap-4 px-6 pt-10 pb-10`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(y,{icon:g,size:`lg`}),(0,N.jsx)(`h1`,{className:`m-0 flex-1 text-[26px] font-semibold tracking-[-0.01em]`,children:`API tests`}),(0,N.jsxs)(d,{variant:`primary`,disabled:!r||_,onClick:()=>m(!0),children:[(0,N.jsx)(T,{size:16,"aria-hidden":`true`}),`New contract set`]})]}),(0,N.jsx)(`p`,{className:`m-0 max-w-[74ch] text-sm leading-relaxed text-muted`,children:`Test the API directly: REST, GraphQL, SOAP and gRPC. Contracts come from an API description or from the calls a browser run saw the application make; scenarios chain calls end to end. Both run straight against the API, with no browser and no model, in a fraction of a UI test's time.`}),o&&(0,N.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:o}),!r&&!o&&(0,N.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),r?.job&&(0,N.jsx)(z,{job:r.job,onStop:()=>v(()=>i.stop())}),r&&(r.sets.length?(0,N.jsxs)(`div`,{className:`flex flex-col gap-6 @2xl:flex-row @2xl:items-start @2xl:gap-8`,children:[(0,N.jsxs)(`nav`,{"aria-label":`Contract sets`,className:`flex min-w-0 flex-col gap-1 @2xl:sticky @2xl:top-6 @2xl:w-[250px] @2xl:flex-none`,children:[(0,N.jsxs)(`span`,{className:`px-3 text-[13px] font-medium text-muted`,children:[`Contract sets (`,r.sets.length,`)`]}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:r.sets.map(t=>{let i=t.last?.contracts;return(0,N.jsx)(`li`,{children:(0,N.jsxs)(`a`,{href:l(`api-tests`,encodeURIComponent(t.id)),"aria-current":S?.id===t.id?`page`:void 0,className:c(`flex min-h-[60px] items-center gap-3 rounded-[12px] px-3 py-2 text-ink no-underline`,S?.id===t.id?`bg-surface-strong hover:text-ink`:`hover:bg-surface-muted hover:text-ink`),children:[r?.job?.running&&r.job.target===t.id?(0,N.jsx)(n,{state:`working`,label:`Working on it`,px:16}):(0,N.jsx)(`span`,{className:c(`size-2.5 flex-none rounded-full`,i?i.counts.failed||i.counts.error?`bg-fail`:`bg-pass`:`bg-line`),"aria-label":i?i.counts.failed||i.counts.error?`failures`:`passed`:`not run`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`truncate text-[15px] font-medium`,children:t.name}),(0,N.jsxs)(`span`,{className:`truncate text-[13px] text-muted`,children:[e(t.contracts,`contract`),t.scenarios?` · ${e(t.scenarios,`scenario`)}`:``,` · `,L(t.at)]})]})]})},t.id)})})]}),S&&(0,N.jsx)(K,{id:S.id,view:r,busy:u||_,act:v,version:C})]}):(0,N.jsxs)(`div`,{className:`flex flex-col items-start gap-3 rounded-[18px] border border-line p-6`,children:[(0,N.jsx)(j,{size:24,"aria-hidden":`true`,className:`text-muted`}),(0,N.jsxs)(`p`,{className:`m-0 max-w-[62ch] leading-relaxed text-ink-2`,children:[`No API contracts yet. Make a set from your OpenAPI, Swagger, WSDL, GraphQL or .proto description`,r.runs.length?`, or from the ${e(r.runs[0].calls,`call`)} the run "${r.runs[0].goal}" saw`:``,`.`]}),(0,N.jsx)(d,{onClick:()=>m(!0),children:`New contract set`})]}))]}),r&&(0,N.jsx)(G,{open:p,onClose:()=>m(!1),view:r,busy:u||_,onMake:e=>v(async()=>{await i.contracts(e),m(!1)})})]})}export{q as ApiTests};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{$ as e,Gt as t,N as n,Q as r,R as i,Vt as a,X as o,Y as s,Z as c,a as l,at as u,fn as d,ht as f,ln as p,n as m,q as h,qt as g,r as _,t as v}from"./status-xNQO8J6U.js";import{n as y,r as b}from"./Response-CgGBxdB7.js";import{_ as x,a as S,b as C,c as w,d as T,g as E,i as D,l as ee,o as te,s as ne,u as re}from"./index-DuYynJ55.js";import{n as O,t as k}from"./when-CHnpLdYw.js";var A={name:`arrow-down`,size:24,node:[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]};A.node;var j=a(A),M=d(p(),1),N=c();function P({id:e}){let[n,a]=(0,M.useState)([]),[c,u]=(0,M.useState)(null),[d,f]=(0,M.useState)(``),[p,h]=(0,M.useState)(``),[_,v]=(0,M.useState)(!1),C=(0,M.useRef)(null),O=(0,M.useRef)(null),k=(0,M.useRef)(!0),[A,P]=(0,M.useState)(!0);(0,M.useEffect)(()=>{let t=!1,n=0;return a([]),u(null),f(``),(async()=>{for(;!t;)try{let r=await g.events(e,n,n>0);if(t||(f(``),u({title:r.title,state:r.state,profile:r.profile}),r.events.length&&(n=r.events[r.events.length-1].n,a(e=>[...e,...r.events])),(r.state===`closed`||r.state===`failed`)&&!r.events.length))return}catch(e){if(t||(f(e.message),e.status===404))return;await new Promise(e=>setTimeout(e,2e3))}})(),()=>{t=!0}},[e]);let F=(0,M.useMemo)(()=>b(n),[n]),I=(0,M.useMemo)(()=>{let e=new Map;for(let t of F.turns.flatMap(e=>e.changes)){let n=e.get(t.path);e.set(t.path,n?{...n,added:n.added+t.added,removed:n.removed+t.removed}:{path:t.path,added:t.added,removed:t.removed})}return[...e.values()]},[F]),L=(0,M.useMemo)(()=>{let e=[];for(let t of F.turns){for(let n of t.tests)n.testFile&&e.push({label:n.ok?`Test`:`Test (failed)`,path:n.testFile,kind:`test`});for(let n of t.reports)e.push({label:/\.html?$/i.test(n.path)?`Report`:`Run report`,path:n.path,kind:`report`})}return e.filter((t,n)=>e.findIndex(e=>e.path===t.path)===n)},[F]),R=(0,M.useRef)(()=>{});l(F.context||F.usage||I.length||L.length?{context:F.context,usage:F.usage,model:F.model?.name,changes:I,outputs:L,busy:c?.state===`busy`||c?.state===`starting`,...I.length?{onCreatePr:()=>R.current()}:{}}:null);let z=c?.state,B=z===`busy`||z===`starting`,V=z===`closed`||z===`failed`,H=F.turns.at(-1),U=!!H&&!H.outcome&&(H.asks.some(e=>e.answer===void 0)||H.waits.some(e=>e.answer===void 0));(0,M.useEffect)(()=>{let e=document.documentElement,t=()=>window.innerHeight+window.scrollY>=e.scrollHeight-48,n=e=>{k.current=e,P(e)},r=window.scrollY,i=()=>{t()?n(!0):window.scrollY<r-2&&n(!1),r=window.scrollY},a=new ResizeObserver(()=>{k.current&&!t()&&window.scrollTo({top:e.scrollHeight})});return C.current&&a.observe(C.current),O.current&&a.observe(O.current),window.addEventListener(`scroll`,i,{passive:!0}),()=>{a.disconnect(),window.removeEventListener(`scroll`,i)}},[]);let ie=()=>{k.current=!0,P(!0),window.scrollTo({top:document.documentElement.scrollHeight,behavior:`smooth`})},[W,G]=(0,M.useState)(null);(0,M.useEffect)(()=>void t.settings().then(G,()=>{}),[]);let[K,q]=(0,M.useState)(!1),[J,Y]=(0,M.useState)({});(0,M.useEffect)(()=>Y({}),[F.headed,F.writeTests]);let X={...S(W),headed:J.headed??F.headed??!1,code:J.code??F.writeTests??!0},Z=(0,M.useCallback)(async e=>{try{await e()}catch(e){f(e.message)}},[]),Q=ee(`chat-${e}`.replace(/[^\w-]/g,``).slice(0,80),e=>{h(e),w(`reply`)}),$=async t=>{if(t.trim()&&!_){v(!0),k.current=!0,P(!0);try{await g.send(e,t.trim()),h(``),f(``),Q.close()}catch(e){f(e.message)}finally{v(!1)}}};return R.current=()=>{if(c?.state===`busy`||c?.state===`starting`||_)return;let e=I.map(e=>`- ${e.path}`).join(`
|
|
2
|
-
`);$(`Open a pull request with the changes you made in this chat:\n${e}\n\nUse a new branch, a clear title and description, and tell me its link.`)},(0,N.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,N.jsxs)(`header`,{className:`sticky top-0 z-20 flex items-center gap-1 border-b border-line-soft bg-bg py-3 pr-16 pl-5`,children:[(0,N.jsx)(m,{}),(0,N.jsx)(`h1`,{className:`m-0 ml-2 min-w-0 flex-1 truncate text-base font-semibold`,children:c?.title||`Chat`}),F.model&&(0,N.jsxs)(`span`,{className:`hidden min-h-9 items-center gap-1.5 rounded-lg px-2 text-sm text-ink-2 sm:inline-flex`,title:`The model this chat uses`,children:[(0,N.jsx)(E,{size:14,fill:`currentColor`,"aria-hidden":`true`,className:`text-accent`}),F.model.name]})]}),(0,N.jsxs)(`main`,{ref:C,className:`mx-auto box-border flex w-full max-w-[960px] flex-auto flex-col gap-8 px-6 pt-8 pb-6`,children:[!c&&!d&&(0,N.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Opening the chat…`}),F.turns.map((t,n)=>(0,N.jsxs)(`section`,{"aria-label":`Message ${n+1}`,className:`flex flex-col gap-5`,children:[(0,N.jsx)(`div`,{className:`ml-auto max-w-[min(85%,640px)] rounded-[18px] bg-surface-strong px-4 py-2.5 text-[15px] leading-relaxed whitespace-pre-wrap text-ink [overflow-wrap:anywhere]`,children:t.user}),(0,N.jsx)(y,{turn:t,live:n===F.turns.length-1&&!V,onAnswer:(t,n)=>Z(()=>g.answer(e,t,n)),onProceed:(t,n)=>Z(()=>g.proceed(e,t,n))})]},t.id)),H?.outcome===`done`&&H.next.length>0&&!B&&!V&&(0,N.jsx)(`div`,{className:`flex flex-wrap gap-2 pl-12`,children:H.next.map(e=>(0,N.jsx)(`button`,{type:`button`,title:e.request===e.label?void 0:e.request,onClick:()=>void $(e.request),className:`inline-flex min-h-10 cursor-pointer items-center rounded-full border border-line bg-bg px-4 text-sm font-medium text-ink-2 hover:border-accent-line hover:bg-accent-soft hover:text-ink`,children:e.label},e.label))}),(F.fatal||V&&F.ended)&&(0,N.jsxs)(`div`,{role:`alert`,className:r(`flex flex-col gap-2 rounded-[14px] px-4 py-3 text-sm leading-relaxed`,F.fatal||z===`failed`?`bg-fail-soft text-fail`:`bg-surface-muted text-ink-2`),children:[(0,N.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:F.fatal||F.ended?.message||(z===`failed`?`ForgeQE stopped unexpectedly.`:`This chat has ended.`)}),F.ended?.stderr&&(0,N.jsx)(`pre`,{className:`m-0 max-h-[200px] overflow-auto rounded-lg bg-bg/60 px-3 py-2 font-mono text-[12px] whitespace-pre-wrap text-ink-2 [overflow-wrap:anywhere]`,children:F.ended.stderr.join(`
|
|
3
|
-
`)}),(0,N.jsxs)(`span`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsx)(`a`,{className:o({size:`sm`}),href:i(),children:`Start a new chat`}),F.fatal&&/model|key|sign/i.test(F.fatal)&&(0,N.jsx)(`a`,{className:o({size:`sm`}),href:i(`settings`,`models`),children:`Models`}),F.fatal&&/runtime|engine|setup/i.test(F.fatal)&&(0,N.jsx)(`a`,{className:o({size:`sm`}),href:i(`settings`,`setup`),children:`Set up`})]})]}),F.notes.map((e,t)=>(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted [overflow-wrap:anywhere]`,children:e},t))]}),(0,N.jsx)(`div`,{ref:O,className:`sticky bottom-0 z-10 bg-gradient-to-t from-bg from-70% to-transparent px-6 pt-4 pb-5`,children:(0,N.jsxs)(`div`,{className:`relative mx-auto flex w-full max-w-[880px] flex-col gap-2`,children:[!A&&B&&(0,N.jsxs)(`button`,{type:`button`,onClick:ie,className:`absolute -top-11 left-1/2 inline-flex min-h-8 -translate-x-1/2 cursor-pointer items-center gap-1.5 rounded-full border border-line bg-bg px-3 text-[13px] font-medium text-ink-2 shadow-sm hover:text-ink`,children:[(0,N.jsx)(j,{size:14,"aria-hidden":`true`}),`Latest activity`]}),(0,N.jsx)(`div`,{"aria-live":`polite`,children:d&&(0,N.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:d})}),(0,N.jsx)(re,{id:`reply`,label:`Reply to ForgeQE`,rows:1,value:p,onChange:h,onSend:()=>void $(p),onStop:()=>Z(()=>g.stop(e)),busy:B&&!U,disabled:V||_||U||Q.running,top:Q.state&&(0,N.jsx)(ne,{state:Q.state,onStop:()=>void Q.stop(),onUndo:Q.undo,onClose:Q.close}),left:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsxs)(`div`,{className:`relative`,children:[(0,N.jsxs)(s,{variant:`ghost`,className:`px-2.5 text-[15px]`,disabled:V,"aria-expanded":K,"aria-haspopup":`dialog`,onClick:()=>q(!K),children:[(0,N.jsx)(x,{size:18,strokeWidth:1.8,"aria-hidden":`true`}),`Tools`,(X.headed||!X.code)&&(0,N.jsx)(`span`,{"aria-hidden":`true`,className:`size-1.5 rounded-full bg-accent`})]}),(0,N.jsx)(T,{open:K,onClose:()=>q(!1),label:`Tools for this chat`,role:`dialog`,side:`auto`,className:`left-0 w-[min(380px,calc(100vw-48px))]`,children:(0,N.jsx)(D,{tools:X,chat:{model:F.model?.name,provider:F.model?.provider},onChange:t=>{let n={};t.headed!==X.headed&&(n.headed=t.headed),t.code!==X.code&&(n.writeTests=t.code),Object.keys(n).length&&(Y({headed:t.headed,code:t.code}),Z(()=>g.settings(e,n)))}})})]}),(0,N.jsx)(te,{running:Q.running,disabled:!p.trim()||V||_||U,onClick:()=>void Q.start(p)})]}),placeholder:V?`This chat has ended`:U?`Answer above to go on`:B?`ForgeQE is working…`:`Reply to ForgeQE…`})]})})]})}function F(e){return e.waiting||e.state===`ready`&&e.outcome===`needs_input`?`waiting`:e.state===`busy`||e.state===`starting`?`working`:e.state===`closed`||e.state===`failed`?`ended`:`done`}var I={working:{label:`Working`,tone:`running`},waiting:{label:`Needs you`,tone:`warn`},done:{label:`Your turn`,tone:`pass`},ended:{label:`Ended`,tone:`neutral`}},L=[{id:`all`,label:`All`},{id:`working`,label:`Working`},{id:`waiting`,label:`Needs you`},{id:`done`,label:`Your turn`},{id:`ended`,label:`Ended`}];function R({c:t}){let n=F(t),a=I[n];return(0,N.jsxs)(`a`,{href:i(`chats`,t.id),className:`group grid min-h-14 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 rounded-[10px] px-3 py-2 text-ink no-underline hover:bg-surface-muted hover:text-ink @3xl:grid-cols-[minmax(0,1fr)_120px_90px_150px_96px]`,children:[(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,N.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2`,children:[n===`waiting`&&(0,N.jsx)(`span`,{"aria-hidden":`true`,className:`size-2 flex-none rounded-full bg-warn`}),(0,N.jsx)(`span`,{className:`truncate text-[14px] font-medium`,children:t.title})]}),(0,N.jsx)(`span`,{className:r(`truncate text-[12.5px]`,t.lastReply?`text-muted`:`text-muted italic`),children:t.lastReply||(n===`working`?`Working on the first answer…`:`No answer yet`)})]}),(0,N.jsx)(`span`,{className:`justify-self-end @3xl:justify-self-start`,children:(0,N.jsx)(v,{tone:a.tone,orb:t.state===`starting`?`waiting`:`working`,children:a.label})}),(0,N.jsx)(`span`,{className:`hidden text-[13px] text-muted tabular-nums @3xl:block`,children:t.turns?e(t.turns,`message`):`—`}),(0,N.jsx)(`span`,{className:`hidden min-w-0 items-center gap-1 truncate text-[13px] text-muted @3xl:flex`,children:t.profile?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(E,{size:11,fill:`currentColor`,"aria-hidden":`true`,className:`flex-none text-accent`}),(0,N.jsx)(`span`,{className:`truncate`,children:t.profile})]}):`Default model`}),(0,N.jsx)(`span`,{className:`hidden text-right text-[13px] text-muted tabular-nums @3xl:block`,children:k(t.lastAt||t.started)})]})}var z=50;function B(){let[e,t]=(0,M.useState)(null),[a,c]=(0,M.useState)(``),[l,d]=(0,M.useState)(`all`),[p,m]=(0,M.useState)(``),[v,y]=(0,M.useState)(z);(0,M.useEffect)(()=>y(z),[l,p]),(0,M.useEffect)(()=>{let e=!1,n=()=>g.list().then(n=>!e&&t(n.chats),t=>!e&&c(t.message));n();let r=setInterval(n,5e3);return()=>{e=!0,clearInterval(r)}},[]);let b=(0,M.useMemo)(()=>{let t={all:0,working:0,waiting:0,done:0,ended:0};for(let n of e||[])t.all++,t[F(n)]++;return t},[e]),x=(0,M.useMemo)(()=>{let t=p.toLowerCase().split(/\s+/).filter(Boolean),n=e=>Date.parse(e.lastAt||e.started)||0;return(e||[]).filter(e=>(l===`all`||F(e)===l)&&t.every(t=>`${e.title} ${e.lastReply||``} ${e.profile||``}`.toLowerCase().includes(t))).sort((e,t)=>n(t)-n(e))},[e,l,p]),S=(0,M.useMemo)(()=>{let e=[];for(let t of x.slice(0,v)){let n=O(t.lastAt||t.started),r=e.find(e=>e.day===n);r?r.chats.push(t):e.push({day:n,chats:[t]})}return e},[x,v]);return(0,N.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,N.jsx)(_,{}),(0,N.jsxs)(`main`,{className:`mx-auto box-border flex w-full max-w-[1180px] flex-col gap-5 px-6 pt-8 pb-10`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(h,{icon:f,size:`lg`}),(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,N.jsx)(`h1`,{className:`m-0 text-[26px] font-semibold tracking-[-0.01em]`,children:`Chats`}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:`Each one is its own ForgeQE agent in your project folder, for as long as forgeqe web runs.`})]}),(0,N.jsxs)(`a`,{className:r(o({variant:`primary`}),`gap-2`),href:i(),children:[(0,N.jsx)(u,{size:16,"aria-hidden":`true`}),`New chat`]})]}),e&&e.length>0&&(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsx)(`div`,{role:`radiogroup`,"aria-label":`Show`,className:`flex flex-wrap gap-1 rounded-full bg-surface-strong p-1`,children:L.map(e=>(0,N.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":l===e.id,onClick:()=>d(e.id),className:r(`inline-flex min-h-8 cursor-pointer items-center gap-1.5 rounded-full border-0 px-3 text-sm font-medium`,l===e.id?`bg-bg text-ink shadow-sm`:`bg-transparent text-muted hover:text-ink`),children:[e.label,(0,N.jsx)(`span`,{className:r(`tabular-nums text-[12px]`,e.id===`waiting`&&b.waiting?`text-warn`:`text-muted`),children:b[e.id]})]},e.id))}),(0,N.jsxs)(`div`,{className:`relative min-w-0 flex-[1_1_240px]`,children:[(0,N.jsx)(C,{size:16,"aria-hidden":`true`,className:`pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-muted`}),(0,N.jsx)(n,{type:`search`,"aria-label":`Find a chat`,value:p,placeholder:`Find a chat`,onChange:e=>m(e.target.value),className:`pl-9`})]})]}),a&&(0,N.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:a}),!e&&!a&&(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Loading…`}),e&&e.length===0&&(0,N.jsxs)(`div`,{className:`flex flex-col items-center gap-4 rounded-[18px] border border-dashed border-line px-6 py-14 text-center`,children:[(0,N.jsx)(h,{icon:f,size:`lg`}),(0,N.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,N.jsx)(`span`,{className:`text-lg font-semibold`,children:`No chats yet`}),(0,N.jsx)(`span`,{className:`max-w-[48ch] text-sm text-muted`,children:`Ask ForgeQE to run test cases, explore a journey, write a test or review requirements. Each chat shows up here while forgeqe web runs.`})]}),(0,N.jsx)(`a`,{className:o({variant:`primary`}),href:i(),children:`Start a chat`})]}),e&&e.length>0&&x.length===0&&(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`No chat matches.`}),x.length>0&&(0,N.jsxs)(`div`,{className:`@container rounded-[14px] border border-line-soft bg-bg`,children:[(0,N.jsxs)(`div`,{"aria-hidden":`true`,className:`hidden grid-cols-[minmax(0,1fr)_120px_90px_150px_96px] gap-x-4 border-b border-line-soft px-6 py-2 text-[12px] font-medium text-muted @3xl:grid`,children:[(0,N.jsx)(`span`,{children:`Chat`}),(0,N.jsx)(`span`,{children:`Status`}),(0,N.jsx)(`span`,{children:`Messages`}),(0,N.jsx)(`span`,{children:`Model`}),(0,N.jsx)(`span`,{className:`text-right`,children:`Last activity`})]}),S.map(e=>(0,N.jsxs)(`section`,{"aria-labelledby":`day-${e.day}`,children:[(0,N.jsxs)(`h2`,{id:`day-${e.day}`,className:`sticky top-0 z-[1] m-0 border-b border-line-soft bg-surface-muted/95 px-6 py-1.5 text-[12px] font-semibold tracking-wide text-muted uppercase backdrop-blur`,children:[e.day,` `,(0,N.jsxs)(`span`,{className:`font-normal tabular-nums`,children:[`· `,e.chats.length]})]}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-1.5`,children:e.chats.map(e=>(0,N.jsx)(`li`,{children:(0,N.jsx)(R,{c:e})},e.id))})]},e.day)),x.length>v&&(0,N.jsxs)(`div`,{className:`flex items-center justify-between gap-3 border-t border-line-soft px-6 py-3 text-[13px] text-muted`,children:[(0,N.jsxs)(`span`,{children:[`Showing `,v,` of `,x.length]}),(0,N.jsxs)(s,{size:`sm`,onClick:()=>y(v+z),children:[`Show `,Math.min(z,x.length-v),` more`]})]})]})]})]})}export{P as Chat,B as Chats};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e,Bt as t,N as n,Nt as r,P as i,Q as a,R as o,Y as s,Yt as c,Z as l,fn as u,ht as d,ln as f,p,q as m,qt as h,r as g,t as _,x as v}from"./status-xNQO8J6U.js";import{t as y}from"./circle-dashed-zjN_W6rR.js";import{n as b}from"./markdown-B1Rz6VFK.js";import{b as x,v as S}from"./index-DuYynJ55.js";var C=u(f(),1),w=l(),T={ready:{label:`Ready`,tone:`pass`},partial:{label:`Ready, some parts need setup`,tone:`warn`},needs_setup:{label:`Needs setup`,tone:`neutral`}},E={models:`Models`,integrations:`Integrations`,monitor:`Monitor`,notifications:`Notifications`,agents:`Agents`,environments:`Environments`,containers:`Containers`,databases:`Databases`};async function D(e,t){try{let{id:t}=await h.start(e,{});location.hash=o(`chats`,t)}catch(e){t(e.message)}}function O({f:t,onScope:n,busy:r}){let[l,u]=(0,C.useState)(null),[f,p]=(0,C.useState)(``),[m,h]=(0,C.useState)(``);(0,C.useEffect)(()=>{c.detail(t.id).then(u,e=>p(e.message))},[t.id]);let g=t.gaps.filter(e=>!e.optional),_=t.gaps.filter(e=>e.optional);return(0,w.jsxs)(`div`,{className:`flex flex-col gap-4 py-4`,children:[[[g,`Needs`],[_,`Would do more with`]].map(([e,t])=>e.length?(0,w.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,w.jsx)(`span`,{className:`text-sm font-medium`,children:t}),(0,w.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-2 p-0`,children:e.map((e,n)=>(0,w.jsxs)(`li`,{className:`flex flex-col gap-0.5 rounded-[10px] bg-bg px-3 py-2 text-sm`,children:[(0,w.jsx)(`span`,{className:a(t===`Needs`?`text-ink`:`text-ink-2`),children:e.missing}),(0,w.jsx)(`span`,{className:`text-[13px] text-muted`,children:e.fix}),e.settings&&(0,w.jsxs)(`a`,{href:o(`settings`,e.settings),className:`inline-flex items-center gap-1 self-start text-[13px] font-medium`,children:[(0,w.jsx)(S,{size:13,"aria-hidden":`true`}),`Set it up in Settings, `,E[e.settings]||e.settings]})]},n))})]},t):null),t.inputs.length>0&&(0,w.jsxs)(`p`,{className:`m-0 text-sm text-ink-2`,children:[`From your request: `,t.inputs.join(`; `),`.`]}),f&&(0,w.jsx)(`p`,{className:`m-0 text-sm text-fail`,children:f}),l&&(0,w.jsxs)(w.Fragment,{children:[l.examples.length>0&&(0,w.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,w.jsx)(`span`,{className:`text-sm font-medium`,children:`Ask for it like this`}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:l.examples.slice(0,4).map(e=>(0,w.jsxs)(s,{size:`sm`,disabled:t.state===`needs_setup`,title:t.state===`needs_setup`?`Set it up first`:`Start a chat with this request`,onClick:()=>void D(e,h),className:`h-auto min-h-8 max-w-full py-1.5 text-left whitespace-normal`,children:[(0,w.jsx)(d,{size:14,"aria-hidden":`true`,className:`flex-none`}),e]},e))}),m&&(0,w.jsx)(`span`,{className:`text-[13px] text-fail`,children:m})]}),l.limits.length>0&&(0,w.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,w.jsx)(`span`,{className:`text-sm font-medium`,children:`What it does not do`}),(0,w.jsx)(`ul`,{className:`m-0 list-disc pl-5 text-sm text-ink-2`,children:l.limits.map(e=>(0,w.jsx)(`li`,{children:e},e))})]}),l.docs.length>0&&(0,w.jsxs)(`details`,{children:[(0,w.jsxs)(`summary`,{className:`cursor-pointer text-sm font-medium`,children:[`How it works (`,e(l.docs.length,`section`),`)`]}),(0,w.jsx)(`div`,{className:`mt-2 flex flex-col gap-4`,children:l.docs.map(e=>(0,w.jsxs)(`section`,{className:`rounded-[12px] bg-bg px-4 py-3`,children:[(0,w.jsx)(`h4`,{className:`m-0 mb-1 text-sm font-semibold`,children:e.heading}),(0,w.jsx)(b,{text:e.text,className:`text-sm`})]},e.heading))})]}),(0,w.jsxs)(`span`,{className:`font-mono text-[11.5px] text-muted [overflow-wrap:anywhere]`,children:[`Tools: `,l.tools.join(`, `)]})]}),(0,w.jsxs)(`label`,{className:`flex flex-wrap items-center gap-3 border-t border-line-soft pt-3 text-sm`,children:[(0,w.jsxs)(`span`,{className:`flex-[1_1_240px]`,children:[`The agent gets its tools`,(0,w.jsx)(`span`,{className:`block text-[13px] text-muted`,children:`agent.capabilities in forgeqe.yaml`})]}),(0,w.jsxs)(i,{value:t.scope,disabled:r,onChange:e=>n(e.target.value),className:`w-[240px]`,children:[(0,w.jsx)(`option`,{value:`auto`,children:`When a request is about it`}),(0,w.jsx)(`option`,{value:`always`,children:`Always`}),(0,w.jsx)(`option`,{value:`off`,children:`Never, in this project`})]})]})]})}function k(){let[e,i]=(0,C.useState)(null),[o,s]=(0,C.useState)(``),[l,u]=(0,C.useState)(``),[d,f]=(0,C.useState)(`all`),[h,b]=(0,C.useState)(``),[S,E]=(0,C.useState)(!1),D=(0,C.useCallback)(()=>c.view().then(i,e=>s(e.message)),[]);(0,C.useEffect)(()=>void D(),[D]);let k=(0,C.useMemo)(()=>{let t=h.toLowerCase().split(/\s+/).filter(Boolean);return(e?.areas||[]).map(e=>({...e,features:e.features.filter(n=>(d===`all`||(d===`ready`?n.state!==`needs_setup`:n.state!==`ready`))&&t.every(t=>`${n.title} ${n.summary} ${e.area}`.toLowerCase().includes(t)))})).filter(e=>e.features.length)},[e,d,h]),A=async(e,t)=>{E(!0);try{i(await c.scope(e,t)),s(``)}catch(e){s(e.message)}finally{E(!1)}},j=e?.counts;return(0,w.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,w.jsx)(g,{}),(0,w.jsxs)(`main`,{className:`mx-auto box-border flex w-full max-w-[920px] flex-auto flex-col gap-5 px-6 pt-10 pb-10`,children:[(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,w.jsx)(m,{icon:t,size:`lg`}),(0,w.jsx)(`h1`,{className:`m-0 flex-1 text-[26px] font-semibold tracking-[-0.01em]`,children:`What's ready`})]}),(0,w.jsx)(`p`,{className:`m-0 max-w-[70ch] text-sm leading-relaxed text-muted`,children:`Everything ForgeQE can do, and whether it works here: in this project, with these settings, on this machine. Each one says what it still needs and where to set it up, and how to ask for it.`}),o&&(0,w.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:o}),!e&&!o&&(0,w.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),e&&j&&(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,w.jsx)(p,{icon:t,label:`Ready`,value:String(j.ready)}),(0,w.jsx)(p,{icon:r,label:`Some parts need setup`,value:String(j.partial)}),(0,w.jsx)(p,{icon:y,label:`Need setup`,value:String(j.needs_setup)})]}),(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,w.jsx)(`div`,{role:`radiogroup`,"aria-label":`Show`,className:`flex gap-1 rounded-full bg-surface-strong p-1`,children:[[`all`,`All`],[`needs`,`Needs setup`],[`ready`,`Ready`]].map(([e,t])=>(0,w.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":d===e,onClick:()=>f(e),className:a(`min-h-8 cursor-pointer rounded-full border-0 px-3.5 text-sm font-medium`,d===e?`bg-bg text-ink shadow-sm`:`bg-transparent text-muted hover:text-ink`),children:t},e))}),(0,w.jsxs)(`div`,{className:`relative min-w-0 flex-[1_1_220px]`,children:[(0,w.jsx)(x,{size:16,"aria-hidden":`true`,className:`pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-muted`}),(0,w.jsx)(n,{type:`search`,"aria-label":`Find a feature`,value:h,placeholder:`Find a feature`,onChange:e=>b(e.target.value),className:`pl-9`})]})]}),k.length===0&&(0,w.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Nothing matches.`}),k.map(e=>(0,w.jsxs)(`section`,{"aria-labelledby":`area-${e.area}`,children:[(0,w.jsx)(`h2`,{id:`area-${e.area}`,className:`m-0 mb-1 text-base font-semibold`,children:e.area}),e.features.map(e=>(0,w.jsx)(v,{title:e.title,meta:(0,w.jsx)(`span`,{className:a(l!==e.id&&`line-clamp-2`),children:e.summary}),open:l===e.id,onToggle:()=>u(l===e.id?``:e.id),state:(0,w.jsxs)(`span`,{className:`flex flex-wrap items-center justify-end gap-1.5`,children:[e.scope!==`auto`&&(0,w.jsx)(_,{tone:`neutral`,icon:!1,children:e.scope===`always`?`Always given`:`Off here`}),(0,w.jsx)(_,{tone:T[e.state].tone,icon:e.state!==`needs_setup`,children:T[e.state].label})]}),children:(0,w.jsx)(O,{f:e,busy:S,onScope:t=>void A(e.id,t)})},e.id))]},e.area)),e.outOfScope.length>0&&(0,w.jsxs)(`section`,{"aria-labelledby":`oos-h`,className:`flex flex-col gap-2 rounded-[14px] border border-line-soft px-4 py-3`,children:[(0,w.jsx)(`h2`,{id:`oos-h`,className:`m-0 text-base font-semibold`,children:`Not what ForgeQE does`}),(0,w.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-1 p-0 text-sm`,children:e.outOfScope.map(e=>(0,w.jsxs)(`li`,{children:[e.what,e.instead?(0,w.jsxs)(`span`,{className:`text-muted`,children:[`; instead: `,e.instead]}):null]},e.what))})]})]})]})]})}export{k as Features};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{I as e,J as t,K as n,L as r,Lt as i,N as a,P as o,Q as s,Qt as c,R as l,Vt as u,Y as d,Z as f,dt as p,fn as m,ft as h,in as g,it as _,ln as v,p as y,pt as b,q as x,r as S,t as C,wt as w}from"./status-xNQO8J6U.js";import{n as T,t as E}from"./terminal-ib42D5b6.js";import{n as D,t as O}from"./markdown-B1Rz6VFK.js";import{t as k}from"./external-link-D2pA4PJ0.js";import{t as A}from"./trash-540pMBsR.js";import{A as j,E as M,N,S as P,w as F,y as I}from"./index-DuYynJ55.js";var L={name:`calendar-plus`,size:24,node:[[`path`,{d:`M16 18h6`,key:`987eiv`}],[`path`,{d:`M16 2v3`,key:`otl347`}],[`path`,{d:`M19 15v6`,key:`10aioa`}],[`path`,{d:`M21 11.5V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h8.3`,key:`jgwkxf`}],[`path`,{d:`M3 9h18`,key:`1pudct`}],[`path`,{d:`M8 2v3`,key:`1ioesn`}]]};L.node;var R=u(L),z={name:`power`,size:24,node:[[`path`,{d:`M12 2v10`,key:`mnfbl`}],[`path`,{d:`M18.4 6.6a9 9 0 1 1-12.77.04`,key:`obofu9`}]]};z.node;var B=u(z),V={name:`search-check`,size:24,node:[[`path`,{d:`m8 11 2 2 4-4`,key:`1sed1v`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`path`,{d:`m21 21-4.3-4.3`,key:`1qie3q`}]]};V.node;var H=u(V),U={name:`timer-off`,size:24,node:[[`path`,{d:`M10 2h4`,key:`n1abiw`}],[`path`,{d:`M4.6 11a8 8 0 0 0 1.7 8.7 8 8 0 0 0 8.7 1.7`,key:`10he05`}],[`path`,{d:`M7.4 7.4a8 8 0 0 1 10.3 1 8 8 0 0 1 .9 10.2`,key:`15f7sh`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M12 12v-2`,key:`fwoke6`}]]};U.node;var W=u(U),G=m(v(),1),K=f(),q={monitor:`Monitor`,suite:`Suite`,run:`Browser run`,heal:`Heal`,"pr-tests":`PR tests`,pack:`Pack`,pipeline:`Pipeline watch`},J={running:{label:`Running`,tone:`running`},passed:{label:`Passed`,tone:`pass`},failed:{label:`Failed`,tone:`fail`},stopped:{label:`Stopped`,tone:`neutral`},timed_out:{label:`Timed out`,tone:`fail`},interrupted:{label:`Interrupted`,tone:`warn`}},Y=e=>{if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:`short`,day:`numeric`,...t.getFullYear()===new Date().getFullYear()?{}:{year:`numeric`},hour:`numeric`,minute:`2-digit`})},X=e=>{if(!e.endedAt)return``;let t=Math.max(0,Math.round((Date.parse(e.endedAt)-Date.parse(e.startedAt))/1e3));return t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`};function Z(e){return e.running?J.running:e.enabled?e.last?J[e.last.status]:{label:`Not run yet`,tone:`neutral`}:{label:`Disabled`,tone:`neutral`}}var Q={pass:`bg-pass`,fail:`bg-fail`,warn:`bg-warn`,running:`bg-accent`,neutral:`bg-line`};function $({label:e,icon:t,children:n}){return(0,K.jsxs)(`div`,{className:`flex min-h-[48px] flex-wrap items-baseline gap-x-4 gap-y-1 border-t border-line-soft py-2.5`,children:[(0,K.jsxs)(`span`,{className:`flex w-[170px] flex-none items-center gap-2 text-sm text-muted`,children:[t&&(0,K.jsx)(t,{size:16,"aria-hidden":`true`,className:`flex-none`}),e]}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 text-sm [overflow-wrap:anywhere]`,children:n})]})}function ee({m:e,rounds:t}){let[n,i]=(0,G.useState)(``);return(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsxs)(`h3`,{className:`m-0 mb-1 flex items-center gap-2 text-base font-semibold`,children:[(0,K.jsx)(M,{size:18,"aria-hidden":`true`,className:`text-accent`}),`Monitor`]}),(0,K.jsx)($,{icon:F,label:`Checks`,children:e.checks.length?(0,K.jsx)(D,{text:e.checks.map(e=>`\`${e.replace(/`/g,``)}\``).join(`, `),className:`text-sm [&_p]:my-0`}):`The checks in forgeqe.yaml (monitor.checks)`}),(0,K.jsxs)($,{icon:N,label:`Alerts after`,children:[e.failAfter,` failing round`,e.failAfter===1?``:`s`,` in a row`,e.remind?`, again every ${e.remind} while it keeps failing`:``]}),(0,K.jsx)($,{icon:I,label:`Alerts go to`,children:e.alerts.length?e.alerts.join(` and `):`Nowhere yet: add Teams or email in Settings, Monitor`}),(0,K.jsxs)($,{icon:h,label:`Each round`,children:[e.parallel,` check`,e.parallel===1?``:`s`,` at once; a recorded run `,e.replay===`trust`?`is trusted`:e.replay===`off`?`is not replayed`:`is verified with one model call`]}),(0,K.jsx)($,{icon:w,label:`Rounds kept in`,children:(0,K.jsx)(O,{path:e.outDir})}),(0,K.jsx)(`p`,{className:`m-0 border-t border-line-soft py-2.5 text-sm`,children:(0,K.jsx)(`a`,{href:l(`settings`,`monitor`),children:`Change the monitor in Settings`})}),(0,K.jsx)(`h4`,{className:`m-0 mt-3 mb-1 text-sm font-semibold`,children:`Latest rounds`}),n&&(0,K.jsx)(`p`,{className:`m-0 text-[13px] text-fail`,children:n}),t.length===0?(0,K.jsx)(`p`,{className:`m-0 border-t border-line-soft py-3 text-sm text-muted`,children:`No rounds yet.`}):(0,K.jsx)(`ul`,{className:`m-0 list-none p-0`,children:t.slice(0,8).map(e=>(0,K.jsxs)(`li`,{className:`flex min-h-[48px] items-center gap-3 border-t border-line-soft py-2`,children:[(0,K.jsxs)(C,{tone:e.counts.failed?`fail`:`pass`,children:[e.counts.passed,`/`,e.counts.total,` passed`]}),(0,K.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-sm`,children:Y(e.startedAt)}),e.report&&(0,K.jsx)(d,{variant:`icon`,size:`icon`,"aria-label":`Open the report of the round of ${Y(e.startedAt)}`,onClick:async()=>i(await r(e.report)),children:(0,K.jsx)(k,{size:16,"aria-hidden":`true`})}),(0,K.jsx)(`a`,{href:l(`reports`,encodeURIComponent(e.key)),className:`text-[13px]`,children:`Details`})]},e.key))})]})}function te({jobId:e,run:t}){let[n,r]=(0,G.useState)(null),[i,a]=(0,G.useState)(``);(0,G.useEffect)(()=>{let n=!1;r(null);let i=()=>c.log(e,t.id).then(e=>!n&&r(e.lines),e=>!n&&a(e.message));i();let o=t.status===`running`?setInterval(i,2e3):void 0;return()=>{n=!0,o&&clearInterval(o)}},[e,t.id,t.status]);let o=Math.max(2,...(n||[]).map(e=>Math.max(0,...(e.match(/`+/g)||[]).map(e=>e.length)))),s="`".repeat(o+1),l=[`**${J[t.status].label}**${t.endedAt?` after ${X(t)}`:``}${t.exitCode!==void 0&&t.exitCode!==null?`, exit ${t.exitCode}`:``}. Started ${Y(t.startedAt)}, ${t.reason===`asked`?`asked for`:`on schedule`}.`,...t.investigating?[``,`_Its failures are being investigated._`]:[],...t.findings?.length?[``,`**Investigated:**`,...t.findings.map(e=>`- ${e.verdict}: ${e.tests.map(e=>`\`${e.replace(/`/g,``)}\``).join(`, `)}${e.branch?` on branch \`${e.branch.replace(/`/g,``)}\``:``}`)]:[],...t.investigationNote?[``,t.investigationNote]:[],``,`${s}text`,...n||[],s].join(`
|
|
2
|
-
`);return(0,K.jsxs)(`div`,{className:`flex flex-col gap-2 rounded-[12px] border border-line-soft bg-surface-muted px-4 py-3`,children:[i&&(0,K.jsx)(`p`,{className:`m-0 text-sm text-fail`,children:i}),!n&&!i?(0,K.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Reading its output…`}):(0,K.jsx)(D,{text:l,className:`text-sm [&_pre]:max-h-[320px] [&_pre]:overflow-auto`})]})}function ne({job:e,rounds:t,busy:r,act:a}){let[o,s]=(0,G.useState)(null),[l,u]=(0,G.useState)(null),[f,m]=(0,G.useState)(!1),h=`${e.running?.id}|${e.last?.id}|${e.last?.status}`;(0,G.useEffect)(()=>{let t=!1;return c.detail(e.id).then(e=>{t||(s(e.runs),u(t=>t??e.runs[0]?.id??null))},()=>{}),()=>{t=!0}},[e.id,h]),(0,G.useEffect)(()=>{u(null),m(!1)},[e.id]);let g=Z(e),v=o?.filter(e=>e.status===`passed`).length??0,x=o?.filter(e=>e.status!==`running`).length??0;return(0,K.jsxs)(`section`,{"aria-labelledby":`job-h`,className:`flex min-w-0 flex-1 flex-col gap-5`,children:[(0,K.jsxs)(`div`,{className:`flex flex-wrap items-start gap-x-3 gap-y-3`,children:[(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-1`,children:[(0,K.jsx)(`h2`,{id:`job-h`,className:`m-0 text-[22px] font-semibold tracking-[-0.01em] [overflow-wrap:anywhere]`,children:e.name}),(0,K.jsxs)(`span`,{className:`text-sm text-muted`,children:[q[e.kind]||e.kind,` · `,e.schedule]})]}),(0,K.jsx)(C,{tone:g.tone,children:g.label}),e.running?(0,K.jsxs)(d,{disabled:r,onClick:()=>a(`stop`),children:[(0,K.jsx)(_,{size:14,fill:`currentColor`,"aria-hidden":`true`}),`Stop`]}):(0,K.jsxs)(d,{variant:`primary`,disabled:r,onClick:()=>a(`run`),children:[(0,K.jsx)(b,{size:16,"aria-hidden":`true`}),`Run now`]})]}),(0,K.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,K.jsx)(y,{icon:p,label:`Runs kept`,value:String(o?.length??`–`)}),(0,K.jsx)(y,{icon:j,label:`Passed`,value:x?`${Math.round(v/x*100)}%`:`–`,note:x?`${v} of ${x}`:void 0}),(0,K.jsx)(y,{icon:i,label:`Next run`,value:e.nextAt?new Date(e.nextAt).toLocaleTimeString([],{hour:`numeric`,minute:`2-digit`}):`–`,note:e.nextAt?Y(e.nextAt):e.enabled?void 0:`Disabled`})]}),(0,K.jsxs)(`div`,{className:`flex flex-col`,children:[(0,K.jsx)($,{icon:E,label:`Runs`,children:(0,K.jsx)(D,{text:`\`${e.command.replace(/`/g,``)}\``,className:`text-sm [&_p]:my-0`})}),(0,K.jsx)($,{icon:i,label:`When`,children:e.schedule}),(0,K.jsx)($,{icon:B,label:`Enabled`,children:(0,K.jsx)(n,{checked:e.enabled,disabled:r,onChange:e=>a(e?`enable`:`disable`),label:`${e.name} enabled`})}),(0,K.jsxs)($,{icon:W,label:`Stopped after`,children:[e.timeoutMs?e.timeoutMs%36e5==0?`${e.timeoutMs/36e5} hour${e.timeoutMs===36e5?``:`s`}`:`${Math.round(e.timeoutMs/6e4)} minutes`:`the service's default`,` of running`]}),(0,K.jsx)($,{icon:T,label:`Tells the team`,children:e.notify?`When it fails, recovers or ends (the notify channels that take job events)`:e.kind===`monitor`?`The monitor sends its own alerts`:`No`}),(0,K.jsx)($,{icon:H,label:`Investigates failures`,children:e.investigate?`Yes, on branches of their own`:`No`}),(0,K.jsxs)($,{icon:R,label:`Added`,children:[Y(e.createdAt),` `,e.by===`agent`?`by ForgeQE's agent, after you agreed`:`from the command line or here`]})]}),e.monitor&&(0,K.jsx)(ee,{m:e.monitor,rounds:t}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(`h3`,{className:`m-0 mb-1 text-base font-semibold`,children:`Runs`}),o?o.length===0?(0,K.jsx)(`p`,{className:`m-0 border-t border-line-soft py-3 text-sm text-muted`,children:`No runs yet. Run now starts one.`}):(0,K.jsx)(`ul`,{className:`m-0 list-none p-0`,children:o.map(t=>(0,K.jsxs)(`li`,{className:`border-t border-line-soft`,children:[(0,K.jsxs)(`button`,{type:`button`,"aria-expanded":l===t.id,onClick:()=>u(l===t.id?null:t.id),className:`flex min-h-[52px] w-full cursor-pointer items-center gap-3 border-0 bg-transparent px-1 py-2 text-left text-ink hover:bg-surface-muted`,children:[(0,K.jsx)(C,{tone:J[t.status].tone,children:J[t.status].label}),(0,K.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-sm`,children:[Y(t.startedAt),(0,K.jsxs)(`span`,{className:`text-muted`,children:[` `,`· `,t.reason===`asked`?`asked for`:`scheduled`,X(t)?` · ${X(t)}`:``]})]}),t.summary?.length?(0,K.jsx)(`span`,{className:`hidden max-w-[40%] truncate text-[13px] text-muted sm:inline`,children:t.summary.at(-1)}):null]}),l===t.id&&(0,K.jsx)(`div`,{className:`pb-3`,children:(0,K.jsx)(te,{jobId:e.id,run:t})})]},t.id))}):(0,K.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Loading…`})]}),(0,K.jsx)(`div`,{className:`flex flex-wrap items-center gap-2 border-t border-line-soft pt-4`,children:f?(0,K.jsxs)(K.Fragment,{children:[(0,K.jsxs)(`span`,{className:`text-sm text-ink-2`,children:[`Remove `,e.name,`? Its runs and logs go with it.`]}),(0,K.jsx)(d,{disabled:r,onClick:()=>a(`remove`),className:`border-fail text-fail hover:bg-fail-soft`,children:`Remove`}),(0,K.jsx)(d,{onClick:()=>m(!1),children:`Keep it`})]}):(0,K.jsxs)(d,{variant:`ghost`,onClick:()=>m(!0),className:`text-fail`,children:[(0,K.jsx)(A,{size:16,"aria-hidden":`true`}),`Remove this job`]})})]})}function re({open:t,onClose:r,commands:i,initial:s,onAdded:l}){let[u,f]=(0,G.useState)(``),[p,m]=(0,G.useState)(`suite`),[h,g]=(0,G.useState)(``),[_,v]=(0,G.useState)(`every`),[y,b]=(0,G.useState)(`30m`),[x,S]=(0,G.useState)(`0 2 * * 1-5`),[C,w]=(0,G.useState)(!0),[T,E]=(0,G.useState)(``),[D,O]=(0,G.useState)(!1);(0,G.useEffect)(()=>{t&&(f(s?.name??``),m(s?.command??`suite`),g(s?.args??``),v(`every`),b(s?.every??`30m`),w(s?.command!==`monitor`),E(``))},[t,s]);let k=async()=>{O(!0),E(``);try{l(await c.add({name:u.trim(),command:p,args:h,..._===`every`?{every:y}:_===`cron`?{cron:x}:{now:!0},notify:C}),u.trim())}catch(e){E(e.message)}finally{O(!1)}},A=`flex flex-col gap-1.5 py-3`;return(0,K.jsx)(e,{open:t,onClose:r,title:`Add a job`,description:`A ForgeQE command the jobs service runs on a schedule, or once now, in a process of its own; it keeps going with this page closed.`,footer:(0,K.jsxs)(K.Fragment,{children:[T&&(0,K.jsx)(`span`,{role:`alert`,className:`mr-auto self-center text-sm text-fail [overflow-wrap:anywhere]`,children:T}),(0,K.jsx)(d,{onClick:r,children:`Cancel`}),(0,K.jsx)(d,{variant:`primary`,disabled:D||!u.trim(),onClick:()=>void k(),children:D?`Adding…`:`Add job`})]}),children:(0,K.jsxs)(`div`,{className:`flex flex-col pt-3`,children:[(0,K.jsxs)(`div`,{className:A,children:[(0,K.jsx)(`label`,{htmlFor:`job-name`,className:`font-medium`,children:`Name`}),(0,K.jsx)(a,{id:`job-name`,value:u,spellCheck:!1,placeholder:`nightly-smoke`,onChange:e=>f(e.target.value)}),(0,K.jsx)(`span`,{className:`text-sm text-muted`,children:`Letters, digits and dashes.`})]}),(0,K.jsxs)(`div`,{className:A,children:[(0,K.jsx)(`label`,{htmlFor:`job-command`,className:`font-medium`,children:`Runs`}),(0,K.jsx)(o,{id:`job-command`,value:p,onChange:e=>m(e.target.value),children:i.map(e=>(0,K.jsxs)(`option`,{value:e,children:[`forgeqe `,e]},e))})]}),(0,K.jsxs)(`div`,{className:A,children:[(0,K.jsx)(`label`,{htmlFor:`job-args`,className:`font-medium`,children:`With`}),(0,K.jsx)(a,{id:`job-args`,value:h,spellCheck:!1,placeholder:p===`monitor`?`Empty: the checks in forgeqe.yaml`:`checks/smoke.yaml --parallel 2`,onChange:e=>g(e.target.value),className:`font-mono text-[13px]`}),(0,K.jsx)(`span`,{className:`text-sm text-muted`,children:`Test case sources and flags, as you would type them after the command. "…" keeps spaces in one. Nothing goes through a shell.`})]}),(0,K.jsxs)(`fieldset`,{className:`m-0 flex flex-col gap-2 border-0 p-0 py-3`,children:[(0,K.jsx)(`legend`,{className:`mb-1 font-medium`,children:`When`}),[[`every`,`Every`],[`cron`,`On a schedule (cron, this machine's time)`],[`once`,`Once, now`]].map(([e,t])=>(0,K.jsxs)(`label`,{className:`flex min-h-10 cursor-pointer items-center gap-3`,children:[(0,K.jsx)(`input`,{type:`radio`,name:`job-when`,checked:_===e,onChange:()=>v(e),className:`size-4 accent-accent`}),(0,K.jsx)(`span`,{className:`flex-none`,children:t}),e===`every`&&_===`every`&&(0,K.jsx)(a,{"aria-label":`Every`,value:y,onChange:e=>b(e.target.value),placeholder:`30m`,className:`max-w-[120px] font-mono text-[13px]`}),e===`cron`&&_===`cron`&&(0,K.jsx)(a,{"aria-label":`Cron schedule`,value:x,onChange:e=>S(e.target.value),className:`max-w-[180px] font-mono text-[13px]`})]},e))]}),(0,K.jsxs)(`div`,{className:`flex items-center gap-4 py-3`,children:[(0,K.jsxs)(`span`,{className:`flex flex-1 flex-col gap-0.5`,children:[(0,K.jsx)(`span`,{className:`font-medium`,children:`Tell the team`}),(0,K.jsx)(`span`,{className:`text-sm text-muted`,children:`When it fails, recovers or ends, on the notify channels that take job events. A monitor sends its own alerts.`})]}),(0,K.jsx)(n,{checked:C,onChange:w,label:`Tell the team`})]})]})})}function ie({sub:e}){let[n,r]=(0,G.useState)(null),[a,o]=(0,G.useState)([]),[u,f]=(0,G.useState)(``),[p,m]=(0,G.useState)(!1),[h,_]=(0,G.useState)(null),v=(0,G.useCallback)(()=>{c.list().then(e=>{r(e),f(``)},e=>f(e.message))},[]);(0,G.useEffect)(v,[v]),(0,G.useEffect)(()=>{g.list().then(e=>o(e.rows.filter(e=>e.scope===`monitor`)),()=>{})},[n?.jobs.map(e=>e.last?.id).join()]);let y=n?.jobs.some(e=>e.running);(0,G.useEffect)(()=>{let e=setInterval(v,y?3e3:2e4);return()=>clearInterval(e)},[v,y]);let b=e?decodeURIComponent(e):``,w=n?.jobs.find(e=>e.id===b)||n?.jobs[0],T=(0,G.useMemo)(()=>n?.jobs.filter(e=>e.kind===`monitor`)??[],[n]),E=(0,G.useMemo)(()=>n?.jobs.filter(e=>e.kind!==`monitor`)??[],[n]),O=async e=>{if(w){m(!0),f(``);try{r(e===`remove`?await c.remove(w.id):await c.act(w.id,e)),e===`remove`&&(location.hash=l(`jobs`))}catch(e){f(e.message)}finally{m(!1)}}},k=e=>{let n=Z(e),r=w?.id===e.id;return(0,K.jsx)(`li`,{children:(0,K.jsxs)(`a`,{href:l(`jobs`,encodeURIComponent(e.id)),"aria-current":r?`page`:void 0,className:s(`flex min-h-[60px] items-center gap-3 rounded-[12px] px-3 py-2 text-ink no-underline`,r?`bg-surface-strong hover:text-ink`:`hover:bg-surface-muted hover:text-ink`),children:[e.running?(0,K.jsx)(t,{label:n.label,px:16}):(0,K.jsx)(`span`,{"aria-label":n.label,className:s(`size-2.5 flex-none rounded-full`,Q[n.tone])}),(0,K.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,K.jsx)(`span`,{className:`truncate text-[15px] font-medium`,children:e.name}),(0,K.jsx)(`span`,{className:`truncate text-[13px] text-muted`,children:[n.label,e.schedule,e.nextAt&&e.enabled?`next ${Y(e.nextAt)}`:``].filter(Boolean).join(` · `)})]})]})},e.id)};return(0,K.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,K.jsx)(S,{}),(0,K.jsxs)(`main`,{className:`@container mx-auto box-border flex w-full max-w-[1180px] flex-auto flex-col gap-4 px-6 pt-10 pb-10`,children:[(0,K.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-2`,children:[(0,K.jsx)(x,{icon:i,size:`lg`}),(0,K.jsx)(`h1`,{className:`m-0 text-[26px] font-semibold tracking-[-0.01em]`,children:`Jobs`}),n&&(0,K.jsx)(C,{tone:n.service.running?`pass`:`neutral`,children:n.service.running?`Service running since ${Y(n.service.startedAt)}`:`Service stopped: jobs wait until it starts`}),(0,K.jsx)(`div`,{className:`flex-auto`}),(0,K.jsxs)(d,{variant:`primary`,disabled:!n,onClick:()=>_({}),children:[(0,K.jsx)(P,{size:16,"aria-hidden":`true`}),`Add a job`]})]}),(0,K.jsx)(`p`,{className:`m-0 max-w-[70ch] text-sm leading-relaxed text-muted`,children:`ForgeQE commands that run on a schedule, or once, in a service of their own, so they keep going while you work on something else or with this page closed: monitors, suites, packs and pipeline watches.`}),u&&(0,K.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:u}),!n&&!u&&(0,K.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),n?.monitor&&!n.monitor.scheduled&&(0,K.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3 rounded-[14px] border border-accent-line bg-accent-soft px-4 py-3`,children:[(0,K.jsx)(M,{size:20,"aria-hidden":`true`,className:`flex-none text-accent`}),(0,K.jsxs)(`span`,{className:`flex min-w-0 flex-[1_1_300px] flex-col gap-0.5 text-sm`,children:[(0,K.jsx)(`span`,{className:`font-medium`,children:`The monitor in forgeqe.yaml is not scheduled`}),(0,K.jsxs)(`span`,{className:`text-ink-2`,children:[n.monitor.checks.length,` check`,n.monitor.checks.length===1?``:`s`,`, every `,n.monitor.every,`. As a job it runs a round each time, with this page closed.`]})]}),(0,K.jsx)(d,{onClick:()=>_({name:`monitor`,command:`monitor`,args:``,every:n.monitor.every}),children:`Schedule it`})]}),n&&(0,K.jsxs)(`div`,{className:`flex flex-col gap-6 @2xl:flex-row @2xl:items-start @2xl:gap-8`,children:[(0,K.jsxs)(`nav`,{"aria-label":`Jobs`,className:`flex min-w-0 flex-col gap-4 @2xl:sticky @2xl:top-6 @2xl:w-[250px] @2xl:flex-none`,children:[(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2 px-3 text-[13px] font-medium text-muted`,children:[(0,K.jsx)(M,{size:14,"aria-hidden":`true`}),`Monitoring (`,T.length,`)`]}),T.length?(0,K.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:T.map(k)}):(0,K.jsx)(`p`,{className:`m-0 px-3 py-2 text-sm text-muted`,children:`No monitor jobs.`})]}),(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsxs)(`span`,{className:`flex items-center gap-2 px-3 text-[13px] font-medium text-muted`,children:[(0,K.jsx)(i,{size:14,"aria-hidden":`true`}),`Other jobs (`,E.length,`)`]}),E.length?(0,K.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:E.map(k)}):(0,K.jsx)(`p`,{className:`m-0 px-3 py-2 text-sm text-muted`,children:`None.`})]}),n.events.length>0&&(0,K.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,K.jsx)(`span`,{className:`px-3 text-[13px] font-medium text-muted`,children:`Recent activity`}),(0,K.jsx)(D,{text:n.events.slice(0,12).map(e=>`- \`${Y(e.at)}\` ${e.text.replace(/([\\`*_[\]<>#|~!])/g,`\\$1`)}`).join(`
|
|
3
|
-
`),className:`px-3 text-[13px] text-ink-2 [&_li]:my-1 [&_ul]:my-0 [&_ul]:pl-4`})]})]}),w?(0,K.jsx)(ne,{job:w,rounds:a,busy:p,act:O}):(0,K.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col items-start gap-3 rounded-[18px] border border-line p-6`,children:[(0,K.jsx)(i,{size:24,"aria-hidden":`true`,className:`text-muted`}),(0,K.jsx)(`p`,{className:`m-0 max-w-[60ch] leading-relaxed text-ink-2`,children:`No jobs yet. Add one to run a suite every night, a monitor every 15 minutes, or watch a CI pipeline.`}),(0,K.jsx)(d,{onClick:()=>_({}),children:`Add a job`})]})]})]}),(0,K.jsx)(re,{open:!!h,onClose:()=>_(null),commands:n?.commands??[],initial:h??void 0,onAdded:(e,t)=>{r(e),_(null);let n=e.jobs.find(e=>e.name===t);n&&(location.hash=l(`jobs`,encodeURIComponent(n.id)))}})]})}export{ie as Jobs};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{N as e,Q as t,R as n,St as r,Vt as i,Y as a,Z as o,fn as s,ht as c,ln as l,m as u,p as d,q as f,qt as p,r as m,t as h,tn as g}from"./status-xNQO8J6U.js";import{i as _}from"./markdown-B1Rz6VFK.js";import{t as v}from"./external-link-D2pA4PJ0.js";import{A as y}from"./index-DuYynJ55.js";var b={name:`accessibility`,size:24,node:[[`circle`,{cx:`16`,cy:`4`,r:`1`,key:`1grugj`}],[`path`,{d:`m18 19 1-7-6 1`,key:`r0i19z`}],[`path`,{d:`m5 8 3-3 5.5 3-2.36 3.5`,key:`9ptxx2`}],[`path`,{d:`M4.24 14.5a5 5 0 0 0 6.88 6`,key:`10kmtu`}],[`path`,{d:`M13.76 17.5a5 5 0 0 0-6.88-6`,key:`2qq6rc`}]]};b.node;var x=i(b),S={name:`image-off`,size:24,node:[[`line`,{x1:`2`,x2:`22`,y1:`2`,y2:`22`,key:`a6p6uj`}],[`path`,{d:`M10.41 10.41a2 2 0 1 1-2.83-2.83`,key:`1bzlo9`}],[`line`,{x1:`13.5`,x2:`6`,y1:`13.5`,y2:`21`,key:`1q0aeu`}],[`line`,{x1:`18`,x2:`21`,y1:`12`,y2:`15`,key:`5mozeu`}],[`path`,{d:`M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59`,key:`mmje98`}],[`path`,{d:`M21 15V5a2 2 0 0 0-2-2H9`,key:`43el77`}]]};S.node;var C=i(S),w={name:`images`,size:24,node:[[`path`,{d:`m22 11-1.296-1.296a2.4 2.4 0 0 0-3.408 0L11 16`,key:`9kzy35`}],[`path`,{d:`M4 8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2`,key:`1t0f0t`}],[`circle`,{cx:`13`,cy:`7`,r:`1`,fill:`currentColor`,key:`1obus6`}],[`rect`,{x:`8`,y:`2`,width:`14`,height:`14`,rx:`2`,key:`1gvhby`}]]};w.node;var T=i(w),E={name:`scan-eye`,size:24,node:[[`path`,{d:`M3 7V5a2 2 0 0 1 2-2h2`,key:`aa7l1z`}],[`path`,{d:`M17 3h2a2 2 0 0 1 2 2v2`,key:`4qcy5o`}],[`path`,{d:`M21 17v2a2 2 0 0 1-2 2h-2`,key:`6vwrx8`}],[`path`,{d:`M7 21H5a2 2 0 0 1-2-2v-2`,key:`ioqczr`}],[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`path`,{d:`M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0`,key:`11ak4c`}]]};E.node;var D=i(E),O={name:`trending-down`,size:24,node:[[`path`,{d:`M16 17h6v-6`,key:`t6n2it`}],[`path`,{d:`m22 17-8.5-8.5-5 5L2 7`,key:`x473p`}]]};O.node;var k=i(O),A={name:`trending-up`,size:24,node:[[`path`,{d:`M16 7h6v6`,key:`box55l`}],[`path`,{d:`m22 7-8.5 8.5-5-5L2 17`,key:`1t1m79`}]]};A.node;var j=i(A),M=s(l(),1),N=o(),P=[`critical`,`serious`,`moderate`,`minor`],F={critical:`fail`,serious:`fail`,moderate:`warn`,minor:`neutral`},I=[{key:`lcp`,label:`LCP`,good:2500,poor:4e3,unit:`ms`},{key:`cls`,label:`CLS`,good:.1,poor:.25,unit:``},{key:`inp`,label:`INP`,good:200,poor:500,unit:`ms`},{key:`fcp`,label:`FCP`,good:1800,poor:3e3,unit:`ms`},{key:`ttfb`,label:`TTFB`,good:800,poor:1800,unit:`ms`},{key:`load`,label:`Load`,good:1/0,poor:1/0,unit:`ms`}],L={same:{label:`Same`,tone:`pass`},changed:{label:`Changed`,tone:`warn`},new:{label:`New baseline`,tone:`neutral`},no_baseline:{label:`No baseline`,tone:`neutral`}},R=e=>new Date(e).toLocaleString([],{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`}),z=(e,t)=>t?e>=1e3?`${(e/1e3).toFixed(1)}s`:`${Math.round(e)}ms`:e.toFixed(3).replace(/0+$/,``).replace(/\.$/,``),B=(e,t)=>`${e} ${t}${e===1?``:`s`}`,V=e=>{try{let t=new URL(e);return`${t.host}${t.pathname}${t.search}`}catch{return e}};function H(e){let t=[];return e.a11y&&t.push(e.a11y.failed?`${B(e.a11y.failed,`rule`)} failed`:`WCAG clean`),e.perf.over&&t.push(`${B(e.perf.over,`page`)} slow`),e.visual?.changed&&t.push(`${e.visual.changed} changed`),e.captured&&t.push(`not compared`),t.join(` · `)||`measured`}var U=e=>e.breaches?`bg-fail`:e.a11y?.critical||e.a11y?.serious||e.visual?.changed?`bg-warn`:`bg-pass`;function W({run:e,standard:t}){let n=e.report,[r,i]=(0,M.useState)(null);if(!n?.accessibility.pages)return(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`This run has no accessibility results: report.accessibility was off, or the run visited no page.`});let a=n.accessibility,o=n.breaches.filter(e=>e.kind===`accessibility`);return(0,N.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[P.map(e=>(0,N.jsx)(d,{label:e.charAt(0).toUpperCase()+e.slice(1),value:String(a.byImpact[e]),note:`elements`},e)),(0,N.jsx)(d,{icon:y,label:`Rules passed`,value:String(a.passed.length),note:`${a.failed.length} failed · ${B(a.pages,`page`)}`})]}),(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[t,` with `,n.engine||`axe`,`. `,n.budgets.accessibility?o.length?`${B(o.length,`budget`)} exceeded.`:`Within the budget.`:`No accessibility budget set: nothing fails on it (quality.budgets.accessibility).`]}),o.map((e,t)=>(0,N.jsxs)(`p`,{className:`m-0 rounded-[10px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:[V(e.page),`: `,e.text]},t)),a.failed.length?(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:a.failed.map(t=>(0,N.jsx)(G,{f:t,examples:e.examples[t.rule]??[],open:r===t.rule,onToggle:()=>i(r===t.rule?null:t.rule)},t.rule))}):(0,N.jsx)(`p`,{className:`m-0 text-sm text-pass`,children:`No rule failed on the pages this run visited.`})]})}function G({f:e,examples:t,open:n,onToggle:r}){return(0,N.jsxs)(`li`,{className:`border-t border-line-soft first:border-t-0`,children:[(0,N.jsxs)(`button`,{type:`button`,"aria-expanded":n,onClick:r,className:`flex min-h-[56px] w-full cursor-pointer items-center gap-3 border-0 bg-transparent px-1 py-2 text-left text-ink hover:bg-surface-muted`,children:[(0,N.jsx)(h,{tone:F[e.impact],className:`w-[92px] flex-none justify-center`,children:e.impact}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`text-sm [overflow-wrap:anywhere]`,children:e.help}),(0,N.jsxs)(`span`,{className:`truncate text-[12px] text-muted`,children:[e.rule,e.wcag?` · WCAG ${e.wcag}${e.level?` (${e.level})`:``}`:``,` · `,B(e.count,`element`),` on `,B(e.pages,`page`)]})]})]}),n&&(0,N.jsxs)(`div`,{className:`mb-3 ml-[104px] flex flex-col gap-2 text-sm max-sm:ml-2`,children:[t.length?t.map((e,t)=>(0,N.jsxs)(`div`,{className:`flex flex-col gap-1 rounded-[10px] bg-surface-muted p-2.5`,children:[(0,N.jsxs)(`span`,{className:`text-[12px] text-muted [overflow-wrap:anywhere]`,children:[V(e.page),e.target?` · ${e.target}`:``]}),e.html&&(0,N.jsx)(`code`,{className:`font-mono text-[12px] whitespace-pre-wrap text-ink-2 [overflow-wrap:anywhere]`,children:e.html})]},t)):(0,N.jsx)(`span`,{className:`text-muted`,children:`No elements were kept for this rule.`}),e.helpUrl&&_(e.helpUrl)===`web`&&(0,N.jsxs)(`a`,{href:e.helpUrl,target:`_blank`,rel:`noreferrer noopener`,className:`inline-flex items-center gap-1 self-start text-[13px]`,children:[`How to fix it `,(0,N.jsx)(v,{size:13,"aria-hidden":`true`})]})]})]})}function K({run:e}){let n=e.report;if(!n?.performance.pages.length)return(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`This run has no timings: the run visited no page.`});let r=(e,t)=>e>t.poor?`poor`:e>t.good?`needs improvement`:`good`,i={poor:`text-fail`,"needs improvement":`text-warn`,good:`text-pass`};return(0,N.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[`Core Web Vitals per page against Google's thresholds: `,(0,N.jsx)(`span`,{className:`text-pass`,children:`good`}),`, `,(0,N.jsx)(`span`,{className:`text-warn`,children:`needs improvement`}),`, `,(0,N.jsx)(`span`,{className:`text-fail`,children:`poor`}),`.`,` `,n.budgets.performance?`Pages over the budget in quality.budgets.performance are marked.`:`No performance budget set: nothing fails on timings (quality.budgets.performance).`]}),(0,N.jsx)(`div`,{className:`overflow-x-auto`,children:(0,N.jsxs)(`table`,{className:`w-full min-w-[640px] border-collapse text-sm`,children:[(0,N.jsx)(`thead`,{children:(0,N.jsxs)(`tr`,{className:`text-left text-[12px] text-muted`,children:[(0,N.jsx)(`th`,{className:`py-2 pr-3 font-medium`,children:`Page`}),I.map(e=>(0,N.jsx)(`th`,{className:`px-2 py-2 text-right font-medium`,children:e.label},e.key)),(0,N.jsx)(`th`,{className:`py-2 pl-2 text-right font-medium`,children:`Requests`})]})}),(0,N.jsx)(`tbody`,{children:n.performance.pages.map((e,n)=>(0,N.jsxs)(`tr`,{className:`border-t border-line-soft align-top`,children:[(0,N.jsxs)(`td`,{className:`py-2 pr-3`,children:[(0,N.jsx)(`span`,{className:`block font-mono text-[12px] [overflow-wrap:anywhere]`,children:V(e.url)}),e.over.length>0&&(0,N.jsx)(`span`,{className:`text-[12px] text-fail`,children:e.over.join(`, `)})]}),I.map(n=>{let a=e[n.key];return(0,N.jsxs)(`td`,{className:t(`px-2 py-2 text-right tabular-nums`,typeof a==`number`&&n.good!==1/0?i[r(a,n)]:typeof a==`number`?`text-ink-2`:`text-muted`),children:[typeof a==`number`?z(a,n.unit):`–`,typeof a==`number`&&n.good!==1/0&&(0,N.jsxs)(`span`,{className:`sr-only`,children:[` (`,r(a,n),`)`]})]},n.key)}),(0,N.jsx)(`td`,{className:`py-2 pl-2 text-right text-muted tabular-nums`,children:e.requests?`${e.requests} · ${e.kb} KB`:`–`})]},n))})]})})]})}function q({run:e,index:t,which:n,label:r}){let[i,a]=(0,M.useState)(``),[o,s]=(0,M.useState)(!1);return(0,M.useEffect)(()=>{let r=!1;return a(``),s(!1),g.image(e,t,n).then(e=>!r&&a(e),()=>!r&&s(!0)),()=>{r=!0}},[e,t,n]),(0,N.jsxs)(`figure`,{className:`m-0 flex min-w-0 flex-col gap-1.5`,children:[(0,N.jsx)(`figcaption`,{className:`text-[12px] font-medium text-muted`,children:r}),i?(0,N.jsx)(`img`,{src:i,alt:`${r} of the page`,className:`block h-auto w-full rounded-[10px] border border-line-soft bg-surface-muted`}):(0,N.jsx)(`span`,{className:`flex h-[120px] items-center justify-center gap-2 rounded-[10px] border border-line-soft bg-surface-muted text-[12px] text-muted`,children:o?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(C,{size:14,"aria-hidden":`true`}),` Not available`]}):`Loading…`})]})}function J({run:n,budget:r,onChange:i}){let[o,s]=(0,M.useState)(null),[c,l]=(0,M.useState)(``),[u,d]=(0,M.useState)(!1),[f,p]=(0,M.useState)(``),[m,_]=(0,M.useState)(null),v=n.visual?.pages??[],b=v.find(e=>e.status===`changed`)?.index??null;(0,M.useEffect)(()=>_(b),[n.id,b]);let x=async e=>{d(!0),p(``);try{i(await e()),s(null),l(``)}catch(e){p(e.message)}finally{d(!1)}};if(!n.visual)return n.captured?(0,N.jsxs)(`div`,{className:`flex flex-col items-start gap-3`,children:[(0,N.jsxs)(`p`,{className:`m-0 text-sm text-ink-2`,children:[`This run captured `,B(n.captured,`page`),` but they were not compared with the baselines yet.`]}),(0,N.jsxs)(a,{variant:`primary`,disabled:u,onClick:()=>x(()=>g.compare(n.id)),children:[(0,N.jsx)(D,{size:16,"aria-hidden":`true`}),`Compare with the baselines`]}),f&&(0,N.jsx)(`p`,{className:`m-0 text-sm text-fail`,children:f})]}):(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`This run has no visual captures: quality.visual.enabled was off, or the run visited no page.`});let S=v.filter(e=>e.status===`changed`);return(0,N.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsxs)(`p`,{className:`m-0 flex-1 text-[13px] text-muted`,children:[`Each page captured with animations frozen and masked regions hidden, against its approved baseline. `,r?`A page over quality.budgets.visual fails the run.`:`No visual budget set: a change does not fail the run (quality.budgets.visual).`]}),S.length>1&&(0,N.jsxs)(a,{disabled:u,onClick:()=>s(S.map(e=>e.url)),children:[`Approve all `,S.length,` changes`]})]}),o&&(0,N.jsxs)(`div`,{role:`alertdialog`,"aria-label":`Approve as baseline`,className:`flex flex-col gap-3 rounded-[12px] border border-accent-line bg-accent-soft p-4`,children:[(0,N.jsxs)(`span`,{className:`font-medium`,children:[`Make this run's capture the baseline of `,o.length===1?V(o[0]):B(o.length,`page`),`?`]}),(0,N.jsx)(`span`,{className:`text-sm text-ink-2`,children:`Later runs are compared with it. Approve only a change that was intended; one that was not is a visual defect.`}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1.5 text-sm`,children:[`Why it changed (kept with the baseline)`,(0,N.jsx)(e,{value:c,maxLength:300,placeholder:`New checkout banner`,onChange:e=>l(e.target.value),className:`max-w-[480px] bg-bg`})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsxs)(a,{variant:`primary`,disabled:u,onClick:()=>x(()=>g.approve(n.id,o,c.trim()||void 0)),children:[(0,N.jsx)(y,{size:16,"aria-hidden":`true`}),`Approve`]}),(0,N.jsx)(a,{onClick:()=>s(null),children:`Cancel`})]})]}),f&&(0,N.jsx)(`p`,{className:`m-0 text-sm text-fail`,children:f}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:v.map(e=>(0,N.jsxs)(`li`,{className:`border-t border-line-soft first:border-t-0`,children:[(0,N.jsxs)(`button`,{type:`button`,"aria-expanded":m===e.index,onClick:()=>_(m===e.index?null:e.index),className:`flex min-h-[52px] w-full cursor-pointer items-center gap-3 border-0 bg-transparent px-1 py-2 text-left text-ink hover:bg-surface-muted`,children:[(0,N.jsx)(T,{size:16,"aria-hidden":`true`,className:`flex-none text-muted`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`text-sm [overflow-wrap:anywhere]`,children:e.title||V(e.url)}),(0,N.jsxs)(`span`,{className:`truncate text-[12px] text-muted`,children:[V(e.url),e.size?` · ${e.size}`:``,e.resized?` · resized ${e.resized}`:``]})]}),e.status===`changed`&&(0,N.jsxs)(`span`,{className:t(`text-sm tabular-nums`,e.over?`text-fail`:`text-warn`),children:[e.diffPercent,`%`,e.limit===void 0?``:` / ${e.limit}%`]}),(0,N.jsx)(h,{tone:e.over?`fail`:L[e.status].tone,children:e.over?`Over budget`:L[e.status].label})]}),m===e.index&&(0,N.jsxs)(`div`,{className:`mb-4 flex flex-col gap-3 px-1`,children:[(0,N.jsxs)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(160px,1fr))] gap-3`,children:[e.images.baseline&&(0,N.jsx)(q,{run:n.id,index:e.index,which:`baseline`,label:`Baseline`}),e.images.current&&(0,N.jsx)(q,{run:n.id,index:e.index,which:`current`,label:`This run`}),e.images.diff&&(0,N.jsx)(q,{run:n.id,index:e.index,which:`diff`,label:`Difference (in red)`})]}),e.status===`changed`&&(0,N.jsxs)(a,{className:`self-start`,disabled:u,onClick:()=>s([e.url]),children:[(0,N.jsx)(y,{size:16,"aria-hidden":`true`}),`Approve as the new baseline`]})]})]},e.index))})]})}function Y({values:e}){if(e.length<2)return null;let t=Math.max(1,...e),n=e.map((n,r)=>`${r/(e.length-1)*96+2},${22-n/t*20}`).join(` `);return(0,N.jsx)(`svg`,{width:`100`,height:`24`,viewBox:`0 0 100 24`,"aria-label":`Violations over the last ${e.length} runs: ${e.join(`, `)}`,role:`img`,className:`flex-none text-muted`,children:(0,N.jsx)(`polyline`,{points:n,fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinejoin:`round`})})}function X({icon:e,className:n,lines:r}){return r.length?(0,N.jsxs)(`span`,{className:t(`flex items-start gap-1.5 text-[13px]`,n),children:[(0,N.jsx)(e,{size:14,"aria-hidden":`true`,className:`mt-0.5 flex-none`}),(0,N.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:r.join(` · `)})]}):null}function Z({trends:e}){return e.length?(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:e.map(e=>{let t=e.a11y.latest?P.reduce((t,n)=>t+(e.a11y.latest[n]||0),0):void 0;return(0,N.jsxs)(`li`,{className:`flex flex-col gap-1.5 border-t border-line-soft py-3 first:border-t-0`,children:[(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-wrap items-center gap-3`,children:[(0,N.jsx)(`span`,{className:`min-w-0 flex-[1_1_240px] font-mono text-[13px] [overflow-wrap:anywhere]`,children:e.page}),(0,N.jsx)(Y,{values:e.a11y.trail}),(0,N.jsxs)(`span`,{className:`text-[12px] text-muted`,children:[B(e.runs,`run`),t===void 0?``:` · ${B(t,`violation`)} now`]})]}),(0,N.jsx)(X,{icon:j,className:`text-fail`,lines:[...e.perf.worse.map(e=>`slower: ${e}`),...e.a11y.newRules.map(e=>`newly failing: ${e}`)]}),(0,N.jsx)(X,{icon:k,className:`text-pass`,lines:[...e.perf.better.map(e=>`faster: ${e}`),...e.a11y.fixedRules.map(e=>`fixed: ${e}`)]})]},e.page)})}):(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`No history yet: every browser run adds each page's accessibility and timings to quality-history.json in the reports folder.`})}function Q({id:e,view:t,onChanged:r}){let[i,o]=(0,M.useState)(null),[s,l]=(0,M.useState)(``),[d,f]=(0,M.useState)(`accessibility`),[m,h]=(0,M.useState)(``);if((0,M.useEffect)(()=>{let t=!1;return o(null),g.run(e).then(e=>{if(t)return;o(e),l(``);let n=e.visual?.pages.some(e=>e.status===`changed`)||!e.visual&&e.captured;f(e.report?.breaches.some(e=>e.kind===`performance`)&&!e.report.accessibility.failed.length?`performance`:n&&!e.report?.accessibility.failed.length?`visual`:e.report?.accessibility.pages?`accessibility`:e.report?.performance.pages.length?`performance`:`visual`)},e=>!t&&l(e.message)),()=>{t=!0}},[e]),s)return(0,N.jsx)(`p`,{className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:s});if(!i)return(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Loading…`});let _=async()=>{try{let{id:e}=await p.start(`Explain the accessibility, performance and visual results of the run in ${i.dir}: call quality_report and visual_compare with run_dir ${i.dir}. Say what matters most to fix first, and why.`,{});location.hash=n(`chats`,e)}catch(e){h(e.message)}},v={accessibility:i.report?.accessibility.failed.length??0,performance:i.report?.performance.pages.filter(e=>e.over.length).length??0,visual:i.visual?.pages.filter(e=>e.status===`changed`).length??0};return(0,N.jsxs)(`section`,{"aria-labelledby":`run-h`,className:`flex min-w-0 flex-1 flex-col gap-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-start gap-3`,children:[(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-1`,children:[(0,N.jsx)(`h2`,{id:`run-h`,className:`m-0 text-[22px] font-semibold tracking-[-0.01em] [overflow-wrap:anywhere]`,children:i.goal}),(0,N.jsxs)(`span`,{className:`text-sm text-muted [overflow-wrap:anywhere]`,children:[R(i.at),` · `,(0,N.jsx)(`span`,{className:`font-mono text-[12px]`,children:i.dir})]})]}),(0,N.jsxs)(a,{variant:`ghost`,onClick:()=>void _(),children:[(0,N.jsx)(c,{size:16,"aria-hidden":`true`}),`Ask in a chat`]})]}),m&&(0,N.jsx)(`p`,{className:`m-0 text-sm text-fail`,children:m}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(u,{label:`Results`,current:d,onPick:f,tabs:[{id:`accessibility`,label:`Accessibility${v.accessibility?` (${v.accessibility})`:``}`},{id:`performance`,label:`Performance${v.performance?` (${v.performance})`:``}`},{id:`visual`,label:`Visual${v.visual?` (${v.visual})`:``}`}]}),(0,N.jsxs)(`div`,{role:`tabpanel`,id:`panel-${d}`,"aria-labelledby":`tab-${d}`,children:[d===`accessibility`&&(0,N.jsx)(W,{run:i,standard:t.standard}),d===`performance`&&(0,N.jsx)(K,{run:i}),d===`visual`&&(0,N.jsx)(J,{run:i,budget:t.budgets.visual,onChange:e=>{o(e),r()}})]})]}),d===`accessibility`&&i.report?.accessibility.pages?(0,N.jsx)(`p`,{className:`m-0 text-[12px] text-muted`,children:t.disclaimer}):null]})}function $({sub:e}){let[i,a]=(0,M.useState)(null),[o,s]=(0,M.useState)(``),[c,l]=(0,M.useState)(e===`trends`?`trends`:`runs`),d=(0,M.useCallback)(()=>{g.view().then(e=>{a(e),s(``)},e=>s(e.message))},[]);(0,M.useEffect)(d,[d]);let p=e&&e!==`trends`?decodeURIComponent(e):``;(0,M.useEffect)(()=>{e===`trends`?l(`trends`):e&&l(`runs`)},[e]);let h=(0,M.useMemo)(()=>i?.runs.find(e=>e.id===p)||i?.runs[0],[i,p]),_=i?.trends.filter(e=>e.perf.worse.length||e.a11y.newRules.length).length??0;return(0,N.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,N.jsx)(m,{}),(0,N.jsxs)(`main`,{className:`@container mx-auto box-border flex w-full max-w-[1180px] flex-auto flex-col gap-4 px-6 pt-10 pb-10`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(f,{icon:r,size:`lg`}),(0,N.jsx)(`h1`,{className:`m-0 flex-1 text-[26px] font-semibold tracking-[-0.01em]`,children:`Quality`})]}),(0,N.jsxs)(`p`,{className:`m-0 max-w-[74ch] text-sm leading-relaxed text-muted`,children:[`What every browser run measures beside its steps: accessibility against `,i?.standard||`WCAG`,`, Core Web Vitals, and each page against its approved visual baseline. Budgets in forgeqe.yaml (quality.budgets) decide what fails a run.`]}),o&&(0,N.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:o}),!i&&!o&&(0,N.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),i&&(0,N.jsx)(u,{label:`Quality`,current:c,onPick:e=>{l(e),e===`trends`?location.hash=n(`quality`,`trends`):location.hash=h?n(`quality`,encodeURIComponent(h.id)):n(`quality`)},tabs:[{id:`runs`,label:`Runs (${i.runs.length})`},{id:`trends`,label:`Trends${_?` (${_} worse)`:``}`}]}),i&&c===`trends`&&(0,N.jsx)(`div`,{role:`tabpanel`,id:`panel-trends`,"aria-labelledby":`tab-trends`,children:(0,N.jsx)(Z,{trends:i.trends})}),i&&c===`runs`&&(i.runs.length?(0,N.jsxs)(`div`,{role:`tabpanel`,id:`panel-runs`,"aria-labelledby":`tab-runs`,className:`flex flex-col gap-6 @2xl:flex-row @2xl:items-start @2xl:gap-8`,children:[(0,N.jsx)(`nav`,{"aria-label":`Runs`,className:`flex min-w-0 flex-col gap-1 @2xl:sticky @2xl:top-6 @2xl:w-[250px] @2xl:flex-none`,children:(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:i.runs.map(e=>(0,N.jsx)(`li`,{children:(0,N.jsxs)(`a`,{href:n(`quality`,encodeURIComponent(e.id)),"aria-current":h?.id===e.id?`page`:void 0,className:t(`flex min-h-[60px] items-center gap-3 rounded-[12px] px-3 py-2 text-ink no-underline`,h?.id===e.id?`bg-surface-strong hover:text-ink`:`hover:bg-surface-muted hover:text-ink`),children:[(0,N.jsx)(`span`,{className:t(`size-2.5 flex-none rounded-full`,U(e)),"aria-label":e.breaches?`over budget`:`within budgets`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`truncate text-[15px] font-medium`,children:e.goal}),(0,N.jsxs)(`span`,{className:`truncate text-[13px] text-muted`,children:[R(e.at),` · `,H(e)]})]})]})},e.id))})}),h&&(0,N.jsx)(Q,{id:h.id,view:i,onChanged:d})]}):(0,N.jsxs)(`div`,{className:`flex flex-col items-start gap-3 rounded-[18px] border border-line p-6`,children:[(0,N.jsx)(x,{size:24,"aria-hidden":`true`,className:`text-muted`}),(0,N.jsx)(`p`,{className:`m-0 max-w-[62ch] leading-relaxed text-ink-2`,children:`No run has measured anything yet. Every browser run checks accessibility, timings and visual changes of the pages it visits; run a flow from a chat or the Record page, and its results show here.`})]}))]})]})}export{$ as Quality};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e,J as t,K as n,L as r,N as i,P as a,Pt as o,Q as s,R as c,Tt as l,Vt as u,Y as d,Z as f,fn as p,it as m,kt as h,ln as g,nn as _,pt as v,q as y,qt as b,r as x,t as S}from"./status-xNQO8J6U.js";import{n as C,r as w,t as T}from"./rotate-ccw-dA-H7K_B.js";import{t as E}from"./markdown-B1Rz6VFK.js";import{t as D}from"./file-chart-column-increasing-FSDL2nUM.js";import{t as O}from"./sticky-note-BuQrlbjE.js";import{t as k}from"./trash-540pMBsR.js";import{A,C as j,D as M,m as ee,p as N,w as P}from"./index-DuYynJ55.js";var F={name:`crosshair`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`22`,x2:`18`,y1:`12`,y2:`12`,key:`l9bcsi`}],[`line`,{x1:`6`,x2:`2`,y1:`12`,y2:`12`,key:`13hhkx`}],[`line`,{x1:`12`,x2:`12`,y1:`6`,y2:`2`,key:`10w3f3`}],[`line`,{x1:`12`,x2:`12`,y1:`22`,y2:`18`,key:`15g9kq`}]]};F.node;var I=u(F),L={name:`dot`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}]]};L.node;var R=u(L),z={name:`hourglass`,size:24,node:[[`path`,{d:`M5 22h14`,key:`ehvnwv`}],[`path`,{d:`M5 2h14`,key:`pdyrp9`}],[`path`,{d:`M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22`,key:`1d314k`}],[`path`,{d:`M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2`,key:`1vvvr6`}]]};z.node;var B=u(z),V={name:`keyboard`,size:24,node:[[`path`,{d:`M10 8h.01`,key:`1r9ogq`}],[`path`,{d:`M12 12h.01`,key:`1mp3jc`}],[`path`,{d:`M14 8h.01`,key:`1primd`}],[`path`,{d:`M16 12h.01`,key:`1l6xoz`}],[`path`,{d:`M18 8h.01`,key:`emo2bl`}],[`path`,{d:`M6 8h.01`,key:`x9i8wu`}],[`path`,{d:`M7 16h10`,key:`wp8him`}],[`path`,{d:`M8 12h.01`,key:`czm47f`}],[`rect`,{width:`20`,height:`16`,x:`2`,y:`4`,rx:`2`,key:`18n3k1`}]]};V.node;var H=u(V),U={name:`mouse-pointer-click`,size:24,node:[[`path`,{d:`M14 4.1 12 6`,key:`ita8i4`}],[`path`,{d:`m5.1 8-2.9-.8`,key:`1go3kf`}],[`path`,{d:`m6 12-1.9 2`,key:`mnht97`}],[`path`,{d:`M7.2 2.2 8 5.1`,key:`1cfko1`}],[`path`,{d:`M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z`,key:`s0h3yz`}]]};U.node;var W=u(U),G={name:`pause`,size:24,node:[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`kaeet6`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`,key:`1wsw3u`}]]};G.node;var te=u(G),K={name:`upload`,size:24,node:[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]};K.node;var ne=u(K),q={name:`variable`,size:24,node:[[`path`,{d:`M8 21s-4-3-4-9 4-9 4-9`,key:`uto9ud`}],[`path`,{d:`M16 3s4 3 4 9-4 9-4 9`,key:`4w2vsq`}],[`line`,{x1:`15`,x2:`9`,y1:`9`,y2:`15`,key:`f7djnv`}],[`line`,{x1:`9`,x2:`15`,y1:`9`,y2:`15`,key:`1shsy8`}]]};q.node;var J=u(q),Y=p(g(),1),X=f(),re={navigate:M,back:w,click:W,dblclick:W,input:H,press:H,select:P,upload:ne,expect:A,wait_for:B,capture:J,note:O,launch:v,double_click:W,type:H,keys:H},ie=e=>re[e]||(e.startsWith(`expect`)?A:R),ae=new Set([`starting`,`recording`,`paused`,`stopping`]);function Z(e,t){let n=Math.max(0,Math.round(((t?Date.parse(t):Date.now())-Date.parse(e))/1e3));return n<3600?`${Math.floor(n/60)}:${String(n%60).padStart(2,`0`)}`:`${Math.floor(n/3600)}h ${Math.floor(n%3600/60)}m`}var oe=e=>new Date(e).toLocaleString([],{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`});async function Q(e){let{id:t}=await b.start(`Turn the recording in ${e} into a test: call write_test with run_dir ${e}. Show me the plan before you write.`,{});location.hash=c(`chats`,t)}async function $(e){let{id:t}=await b.start(`Replay the desktop workflow ${e}: call desktop_replay with workflow ${e}, and tell me how each step went.`,{});location.hash=c(`chats`,t)}function se({s:e,live:t,onDelete:n}){let r=ie(e.op);return(0,X.jsxs)(`li`,{className:`group flex min-h-[44px] items-start gap-3 border-t border-line-soft py-2 first:border-t-0`,children:[(0,X.jsx)(`span`,{className:`w-6 flex-none pt-0.5 text-right text-[13px] text-muted tabular-nums`,children:e.n}),(0,X.jsx)(r,{size:16,"aria-hidden":`true`,className:s(`mt-0.5 flex-none`,e.op.startsWith(`expect`)?`text-pass`:`text-muted`)}),(0,X.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,X.jsx)(`span`,{className:`text-sm [overflow-wrap:anywhere]`,children:e.text}),(e.note||e.dynamic||e.inferred||e.case_step)&&(0,X.jsxs)(`span`,{className:`flex flex-wrap gap-x-2 text-[12px] text-muted`,children:[e.case_step?(0,X.jsxs)(`span`,{children:[`case step `,e.case_step]}):null,e.dynamic&&(0,X.jsx)(`span`,{children:`value changes between runs`}),e.inferred&&(0,X.jsx)(`span`,{children:`added by ForgeQE`}),e.note&&(0,X.jsxs)(`span`,{className:`[overflow-wrap:anywhere]`,children:[`note: `,e.note]})]})]}),t&&e.n>1&&(0,X.jsx)(d,{variant:`icon`,size:`icon`,"aria-label":`Delete step ${e.n}`,onClick:n,className:`size-8 flex-none opacity-60 group-hover:opacity-100`,children:(0,X.jsx)(k,{size:15,"aria-hidden":`true`})})]})}function ce({s:e,send:n,busy:r}){let[a,o]=(0,Y.useState)(``),[,c]=(0,Y.useState)(0);(0,Y.useEffect)(()=>{let e=setInterval(()=>c(e=>e+1),1e3);return()=>clearInterval(e)},[]);let l=(0,Y.useRef)(null);(0,Y.useEffect)(()=>{l.current&&(l.current.scrollTop=l.current.scrollHeight)},[e.log.length]);let u=e.kind===`desktop`,f=e.state===`paused`,p=e.log.at(-1)?.level===`warn`&&/press Stop again/i.test(e.log.at(-1).text),g=Math.max(0,...e.steps.map(e=>e.case_step||0)),_=(t,i,a,o)=>(0,X.jsxs)(d,{disabled:r||e.state===`starting`,onClick:()=>n({cmd:t}),title:o,children:[(0,X.jsx)(a,{size:16,"aria-hidden":`true`}),i]},t);return(0,X.jsxs)(`div`,{className:`flex flex-col gap-5`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3 rounded-[14px] border border-line-soft px-4 py-3`,children:[f?(0,X.jsx)(`span`,{"aria-hidden":`true`,className:`size-3 flex-none rounded-full bg-warn`}):(0,X.jsx)(t,{state:e.state===`starting`?`waiting`:e.state===`stopping`?`working`:`recording`,px:20}),(0,X.jsxs)(`span`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-0.5`,children:[(0,X.jsx)(`span`,{className:`font-medium [overflow-wrap:anywhere]`,children:e.name}),(0,X.jsxs)(`span`,{className:`truncate text-[13px] text-muted`,children:[e.state===`starting`?u?`Starting ${e.app}…`:`Opening the browser…`:e.state===`stopping`?`Saving the workflow…`:f?`Paused: what you do now is not recorded`:`Recording`,` · `,Z(e.startedAt),` ·`,` `,u?`${e.app}, a desktop app`:e.url]})]}),!u&&(0,X.jsxs)(d,{disabled:r||e.state===`starting`,onClick:()=>n({cmd:`pause`}),children:[f?(0,X.jsx)(v,{size:16,"aria-hidden":`true`}):(0,X.jsx)(te,{size:16,"aria-hidden":`true`}),f?`Resume`:`Pause`]}),(0,X.jsxs)(d,{disabled:r||e.state===`stopping`,onClick:()=>n({cmd:`stop`,...p?{force:!0}:{}}),className:`border-fail bg-fail text-white hover:bg-fail hover:text-white hover:opacity-90`,children:[(0,X.jsx)(m,{size:14,fill:`currentColor`,"aria-hidden":`true`}),p?`Stop anyway`:`Stop and save`]})]}),u?(0,X.jsxs)(`p`,{className:`m-0 rounded-[12px] bg-accent-soft px-4 py-3 text-sm leading-relaxed text-ink-2`,children:[e.app,` is open on this computer: do the steps in it. Only clicks and keys in its own windows are recorded; password fields are saved as secret names, never as what you type. In the app, `,(0,X.jsx)(`strong`,{children:`Ctrl+Shift+F11`}),` over a control adds a check of what it shows, and `,(0,X.jsx)(`strong`,{children:`Ctrl+Shift+F12`}),` or closing the app stops.`]}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`p`,{className:`m-0 rounded-[12px] bg-accent-soft px-4 py-3 text-sm leading-relaxed text-ink-2`,children:[`The browser is open on this computer: do the steps there. The Recorder panel in the page does the same as these buttons; in the page, `,e.leader,` then a letter: `,(0,X.jsx)(`strong`,{children:`A`}),` check, `,(0,X.jsx)(`strong`,{children:`V`}),` keep a value, `,(0,X.jsx)(`strong`,{children:`W`}),` wait for,`,` `,(0,X.jsx)(`strong`,{children:`D`}),` test data, `,(0,X.jsx)(`strong`,{children:`N`}),` note, `,(0,X.jsx)(`strong`,{children:`P`}),` pause, `,(0,X.jsx)(`strong`,{children:`Z`}),` undo, `,(0,X.jsx)(`strong`,{children:`S`}),` stop.`]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-2`,role:`toolbar`,"aria-label":`Recorder`,children:[_(`assert`,`Check an element`,I,`Pick an element in the page to check`),_(`variable`,`Keep a value`,J,`Pick an element whose text later steps use`),_(`wait`,`Wait for`,B,`Pick an element the test waits for`),_(`data`,`Test data`,h,`The last value you typed becomes test data`),_(`note`,`Note`,O,`A note for the step, for whoever reads the test`),_(`undo`,`Undo`,ee,`Remove the last step`)]}),(0,X.jsxs)(`form`,{className:`flex flex-wrap gap-2`,onSubmit:e=>{e.preventDefault(),a.trim()&&(n({cmd:`chat`,text:a.trim()}),o(``))},children:[(0,X.jsx)(`label`,{htmlFor:`rec-check`,className:`sr-only`,children:`Describe a check`}),(0,X.jsx)(i,{id:`rec-check`,value:a,maxLength:2e3,placeholder:`Describe a check: the total shows "$40.00", or note: …`,onChange:e=>o(e.target.value),className:`min-w-0 flex-[1_1_320px]`}),(0,X.jsxs)(d,{type:`submit`,variant:`primary`,disabled:r||!a.trim()||e.state===`starting`,children:[(0,X.jsx)(N,{size:16,"aria-hidden":`true`}),`Add`]})]})]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap items-start gap-x-6 gap-y-5`,children:[(0,X.jsxs)(`section`,{"aria-labelledby":`rec-steps`,className:`flex min-w-0 flex-[999_1_420px] flex-col gap-2 rounded-[14px] border border-line-soft px-4 py-3`,children:[(0,X.jsxs)(`h2`,{id:`rec-steps`,className:`m-0 flex items-center gap-2 text-base font-semibold`,children:[(0,X.jsx)(P,{size:18,"aria-hidden":`true`,className:`text-accent`}),`Steps`,(0,X.jsx)(`span`,{className:`text-sm font-normal text-muted`,children:e.summary})]}),e.steps.length?(0,X.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,"aria-live":`polite`,children:e.steps.map(e=>(0,X.jsx)(se,{s:e,live:!u,onDelete:()=>n({cmd:`delete`,n:e.n})},`${e.n}-${e.text}`))}):(0,X.jsx)(`p`,{className:`m-0 py-2 text-sm text-muted`,children:e.state===`starting`?u?`Starting ${e.app}…`:`Opening the browser…`:`Nothing yet: do the first step in ${u?e.app:`the browser`}.`})]}),(0,X.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_300px] flex-col gap-5`,children:[e.case&&(0,X.jsxs)(`section`,{"aria-labelledby":`rec-case`,className:`flex flex-col gap-2 rounded-[14px] border border-line-soft px-4 py-3`,children:[(0,X.jsxs)(`h2`,{id:`rec-case`,className:`m-0 flex items-center gap-2 text-base font-semibold`,children:[(0,X.jsx)(P,{size:18,"aria-hidden":`true`,className:`text-accent`}),e.case.id]}),(0,X.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[e.case.title,`. Each step you record belongs to the case step you are on: pick one to record it.`]}),(0,X.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,children:e.case.steps.map(t=>{let i=e.steps.some(e=>e.case_step===t.n);return(0,X.jsx)(`li`,{className:`border-t border-line-soft first:border-t-0`,children:(0,X.jsxs)(`button`,{type:`button`,disabled:r,"aria-current":t.n===g?`step`:void 0,onClick:()=>n({cmd:`case_step`,n:t.n}),className:s(`flex w-full cursor-pointer items-start gap-2 rounded-[10px] border-0 bg-transparent px-2 py-2 text-left text-sm text-ink hover:bg-surface-muted`,t.n===g&&`bg-accent-soft`),children:[i?(0,X.jsx)(A,{size:16,"aria-hidden":`true`,className:`mt-0.5 flex-none text-pass`}):(0,X.jsx)(`span`,{className:`mt-0.5 w-4 flex-none text-center text-[12px] text-muted`,children:t.n}),(0,X.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,X.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:t.action}),t.expected&&(0,X.jsxs)(`span`,{className:`text-[12px] text-muted [overflow-wrap:anywhere]`,children:[`Expect: `,t.expected]})]})]})},t.n)})}),(0,X.jsx)(d,{disabled:r,onClick:()=>n({cmd:`case_next`}),className:`self-start`,children:`Next case step`})]}),(0,X.jsxs)(`section`,{"aria-labelledby":`rec-log`,className:`flex flex-col gap-2 rounded-[14px] border border-line-soft px-4 py-3`,children:[(0,X.jsx)(`h2`,{id:`rec-log`,className:`m-0 text-base font-semibold`,children:`What the recorder says`}),(0,X.jsx)(`div`,{ref:l,className:`flex max-h-[280px] flex-col gap-1 overflow-auto text-[13px]`,"aria-live":`polite`,children:e.log.length?e.log.map((e,t)=>(0,X.jsx)(`p`,{className:s(`m-0 [overflow-wrap:anywhere]`,e.level===`warn`?`text-warn`:e.level===`error`?`text-fail`:`text-ink-2`),children:e.text},t)):(0,X.jsxs)(`p`,{className:`m-0 text-muted`,children:[`Waiting for `,u?`the app`:`the browser`,`…`]})})]})]})]})]})}function le({s:t}){let n=t.result,[i,a]=(0,Y.useState)(``),[o,s]=(0,Y.useState)(!1);if(!n)return null;let c=t.kind===`desktop`;return(0,X.jsxs)(`section`,{"aria-labelledby":`rec-result`,className:`flex flex-col gap-3 rounded-[14px] border border-line-soft p-4`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,X.jsx)(`h2`,{id:`rec-result`,className:`m-0 flex-1 text-base font-semibold [overflow-wrap:anywhere]`,children:t.name}),(0,X.jsx)(S,{tone:n.ok?`pass`:`fail`,children:n.ok?`Recorded`:`Not recorded`})]}),(0,X.jsxs)(`p`,{className:`m-0 text-sm text-ink-2`,children:[n.ok?n.summary||t.summary:n.error||`Nothing was recorded.`,` `,t.endedAt&&(0,X.jsxs)(`span`,{className:`text-muted`,children:[`· `,Z(t.startedAt,t.endedAt)]})]}),n.ok&&(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-2 text-sm`,children:[(0,X.jsx)(S,{tone:`neutral`,icon:!1,children:e(t.steps.length,`step`)}),(0,X.jsxs)(S,{tone:n.checks?`pass`:`warn`,children:[n.checks,` check`,n.checks===1?``:`s`]}),n.variables.length>0&&(0,X.jsxs)(S,{tone:`neutral`,icon:!1,children:[`kept: `,n.variables.join(`, `)]}),n.testData.length>0&&(0,X.jsxs)(S,{tone:`neutral`,icon:!1,children:[`test data: `,n.testData.join(`, `)]})]}),!c&&n.secrets.length>0&&(0,X.jsxs)(`p`,{className:`m-0 text-sm text-ink-2`,children:[`The test reads`,` `,n.secrets.map((e,t)=>(0,X.jsxs)(`span`,{children:[t?`, `:``,(0,X.jsx)(`code`,{className:`font-mono text-[13px]`,children:e})]},e)),` `,`from the environment: what you typed there was not saved. Set `,n.secrets.length===1?`it`:`them`,` before the test runs.`]}),n.caseGaps.length>0&&(0,X.jsx)(`ul`,{className:`m-0 flex flex-col gap-1 pl-5 text-sm text-warn`,children:n.caseGaps.map(e=>(0,X.jsxs)(`li`,{children:[`No check for case step `,e.n,`: expects “`,e.expected,`”`]},e.n))}),(n.notes??[]).length>0&&(0,X.jsx)(`ul`,{className:`m-0 flex flex-col gap-1 pl-5 text-sm text-ink-2`,children:n.notes.map((e,t)=>(0,X.jsx)(`li`,{children:e},t))}),n.skipped.length>0&&(0,X.jsx)(`ul`,{className:`m-0 flex flex-col gap-1 pl-5 text-sm text-muted`,children:n.skipped.map((e,t)=>(0,X.jsxs)(`li`,{children:[`Not recorded: `,e.action,`: `,e.reason]},t))}),(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[c&&n.workflow&&(0,X.jsxs)(d,{variant:`primary`,disabled:o,onClick:async()=>{s(!0);try{await $(n.workflow)}catch(e){a(e.message),s(!1)}},children:[(0,X.jsx)(T,{size:16,"aria-hidden":`true`}),`Replay it`]}),c&&n.report&&(0,X.jsxs)(d,{onClick:async()=>a(await r(n.report)),children:[(0,X.jsx)(D,{size:16,"aria-hidden":`true`}),`Open the report`]}),!c&&n.ok&&(0,X.jsxs)(d,{variant:`primary`,disabled:o,onClick:async()=>{s(!0);try{await Q(t.runDir)}catch(e){a(e.message),s(!1)}},children:[(0,X.jsx)(N,{size:16,"aria-hidden":`true`}),`Write a test from it`]}),!c&&n.ok&&(0,X.jsxs)(d,{onClick:async()=>a(await r(`${t.runDir}/trace.md`)),children:[(0,X.jsx)(l,{size:16,"aria-hidden":`true`}),`Read the steps`]}),(0,X.jsx)(`span`,{className:`text-sm`,children:(0,X.jsx)(E,{path:c&&n.workflow?n.workflow:t.runDir})}),i&&(0,X.jsx)(`span`,{className:`text-[13px] text-fail`,children:i})]})]})}function ue({view:e,busy:t,onStart:r}){let[l,u]=(0,Y.useState)(e.session?.kind===`desktop`&&e.desktop.available?`desktop`:`web`),[f,p]=(0,Y.useState)(e.desktop.apps[0]??``),[m,h]=(0,Y.useState)(e.apps.length?`app`:`url`),[g,_]=(0,Y.useState)(e.apps[0]?.name??``),[v,y]=(0,Y.useState)(``),[b,x]=(0,Y.useState)(``),[S,C]=(0,Y.useState)(``),[w,T]=(0,Y.useState)(e.environment??``),[E,D]=(0,Y.useState)(!1),O=`flex flex-col gap-1.5`,k=l===`desktop`?e.desktop.available&&!!f:m===`app`?!!g:/^https?:\/\/\S+$/i.test(v.trim()),A=(e,t,n,r,i=!1)=>(0,X.jsxs)(`label`,{className:s(`flex min-h-[64px] flex-[1_1_240px] items-start gap-3 rounded-[12px] border px-3 py-2.5`,l===e?`border-accent bg-accent-soft`:`border-line-soft`,i?`cursor-not-allowed opacity-60`:`cursor-pointer hover:bg-surface-muted`),children:[(0,X.jsx)(`input`,{type:`radio`,name:`rec-kind`,checked:l===e,disabled:i,onChange:()=>u(e),className:`mt-1 size-4 accent-accent`}),(0,X.jsx)(r,{size:18,"aria-hidden":`true`,className:`mt-0.5 flex-none text-accent`}),(0,X.jsxs)(`span`,{className:`flex min-w-0 flex-col gap-0.5`,children:[(0,X.jsx)(`span`,{className:`text-sm font-medium`,children:t}),(0,X.jsx)(`span`,{className:`text-[13px] text-muted`,children:n})]})]});return(0,X.jsxs)(`form`,{className:`flex flex-col gap-4 rounded-[14px] border border-line-soft p-4`,onSubmit:t=>{if(t.preventDefault(),k){if(l===`desktop`)return r({kind:`desktop`,app:f,...b.trim()?{name:b.trim()}:{},...w&&w!==e.environment?{env:w}:{}});r({...m===`app`?{app:g}:{url:v.trim()},...b.trim()?{name:b.trim()}:{},...S.trim()?{case:S.trim()}:{},...w&&w!==e.environment?{env:w}:{},signedIn:E})}},children:[(0,X.jsx)(`h2`,{className:`m-0 text-base font-semibold`,children:`New recording`}),(0,X.jsxs)(`fieldset`,{className:`m-0 flex flex-col gap-2 border-0 p-0`,children:[(0,X.jsx)(`legend`,{className:`mb-1.5 text-sm font-medium`,children:`What to record`}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[A(`web`,`A web page`,`In a browser, with the Recorder panel in the page; a chat turns it into a test.`,M),A(`desktop`,`A desktop app`,e.desktop.available?`A Windows app from your settings; it is saved as a workflow that replays with no model.`:e.desktop.reason||`Windows only.`,j,!e.desktop.available)]})]}),l===`desktop`?(0,X.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,X.jsx)(`label`,{htmlFor:`rec-desktop-app`,className:`text-sm font-medium`,children:`App`}),e.desktop.apps.length?(0,X.jsx)(a,{id:`rec-desktop-app`,value:f,onChange:e=>p(e.target.value),className:`max-w-[420px]`,children:e.desktop.apps.map(e=>(0,X.jsx)(`option`,{value:e,children:e},e))}):(0,X.jsxs)(`p`,{className:`m-0 text-sm text-muted`,children:[`No desktop apps yet: add one in `,(0,X.jsx)(`a`,{href:c(`settings`,`environments`),children:`Settings, Environments`}),`.`]})]}):(0,X.jsxs)(`fieldset`,{className:`m-0 flex flex-col gap-2 border-0 p-0`,children:[(0,X.jsx)(`legend`,{className:`mb-1.5 text-sm font-medium`,children:`Start on`}),(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[e.apps.length>0&&(0,X.jsxs)(`label`,{className:`flex min-h-10 cursor-pointer items-center gap-2 text-sm`,children:[(0,X.jsx)(`input`,{type:`radio`,name:`rec-from`,checked:m===`app`,onChange:()=>h(`app`),className:`size-4 accent-accent`}),`An app of `,e.environment?`the ${e.environment} environment`:`the environment`]}),(0,X.jsxs)(`label`,{className:`flex min-h-10 cursor-pointer items-center gap-2 text-sm`,children:[(0,X.jsx)(`input`,{type:`radio`,name:`rec-from`,checked:m===`url`,onChange:()=>h(`url`),className:`size-4 accent-accent`}),`A page`]})]}),m===`app`?(0,X.jsx)(a,{"aria-label":`App`,value:g,onChange:e=>_(e.target.value),className:`max-w-[420px]`,children:e.apps.map(e=>(0,X.jsxs)(`option`,{value:e.name,children:[e.name,` · `,e.url]},e.name))}):(0,X.jsx)(i,{"aria-label":`Page address`,type:`url`,value:v,spellCheck:!1,placeholder:`https://shop.example.com/`,onChange:e=>y(e.target.value),className:`max-w-[520px]`})]}),(0,X.jsxs)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(240px,1fr))] gap-4`,children:[(0,X.jsxs)(`div`,{className:O,children:[(0,X.jsx)(`label`,{htmlFor:`rec-name`,className:`text-sm font-medium`,children:`What the test does`}),(0,X.jsx)(i,{id:`rec-name`,value:b,maxLength:200,placeholder:`Checkout with a saved card`,onChange:e=>x(e.target.value)})]}),l===`web`&&(0,X.jsxs)(`div`,{className:O,children:[(0,X.jsxs)(`label`,{htmlFor:`rec-case`,className:`text-sm font-medium`,children:[`Test case `,(0,X.jsx)(`span`,{className:`font-normal text-muted`,children:`(optional)`})]}),(0,X.jsx)(i,{id:`rec-case`,value:S,spellCheck:!1,placeholder:`SHOP-12, ado:1234 or a file`,onChange:e=>C(e.target.value)})]}),e.environments.length>1&&(l===`desktop`||m===`app`)&&(0,X.jsxs)(`div`,{className:O,children:[(0,X.jsx)(`label`,{htmlFor:`rec-env`,className:`text-sm font-medium`,children:`Environment`}),(0,X.jsx)(a,{id:`rec-env`,value:w,onChange:e=>T(e.target.value),children:e.environments.map(e=>(0,X.jsx)(`option`,{value:e,children:e},e))})]})]}),l===`web`&&e.logins.length>0&&(0,X.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,X.jsxs)(`span`,{className:`flex flex-1 flex-col gap-0.5`,children:[(0,X.jsx)(`span`,{className:`text-sm font-medium`,children:`Start signed in`}),(0,X.jsxs)(`span`,{className:`text-[13px] text-muted`,children:[`With the saved sign-ins (`,e.logins.join(`, `),`). Off: record the sign-in too; passwords are saved as variable names, never as typed.`]})]}),(0,X.jsx)(n,{checked:E,onChange:D,label:`Start signed in`})]}),(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,X.jsxs)(d,{type:`submit`,variant:`primary`,disabled:t||!k,children:[(0,X.jsx)(o,{size:16,"aria-hidden":`true`}),t?l===`desktop`?`Starting the app…`:`Opening the browser…`:`Start recording`]}),(0,X.jsx)(`span`,{className:`text-[13px] text-muted`,children:l===`desktop`?`The app starts on this computer; do the steps in it.`:`A browser opens on this computer, with the Recorder panel in the page.`})]})]})}function de({rows:e}){let[t,n]=(0,Y.useState)(``);return e.length?(0,X.jsxs)(`section`,{"aria-labelledby":`rec-list`,className:`flex flex-col gap-2`,children:[(0,X.jsx)(`h2`,{id:`rec-list`,className:`m-0 text-base font-semibold`,children:`Recordings`}),t&&(0,X.jsx)(`p`,{className:`m-0 text-[13px] text-fail`,children:t}),(0,X.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:e.map(e=>(0,X.jsxs)(`li`,{className:`flex min-h-[60px] flex-wrap items-center gap-x-3 gap-y-2 border-t border-line-soft py-2 first:border-t-0`,children:[(0,X.jsx)(`span`,{"aria-hidden":`true`,className:s(`size-2.5 flex-none rounded-full`,e.ok?`bg-pass`:`bg-fail`)}),e.kind===`desktop`?(0,X.jsx)(j,{size:16,"aria-label":`Desktop app`,className:`flex-none text-muted`}):(0,X.jsx)(M,{size:16,"aria-label":`Web page`,className:`flex-none text-muted`}),(0,X.jsxs)(`span`,{className:`flex min-w-0 flex-[1_1_280px] flex-col gap-0.5`,children:[(0,X.jsx)(`span`,{className:`truncate text-[15px] font-medium`,children:e.name}),(0,X.jsxs)(`span`,{className:`flex flex-wrap items-center gap-x-2 text-[13px] text-muted`,children:[(0,X.jsx)(C,{size:13,"aria-hidden":`true`}),oe(e.startedAt),` · `,e.steps,` step`,e.steps===1?``:`s`,` · `,e.checks,` check`,e.checks===1?``:`s`,e.caseId?` · ${e.caseId}`:``,e.app?` · ${e.app}`:``]})]}),e.trace&&(0,X.jsxs)(d,{size:`sm`,onClick:async()=>n(await r(e.trace)),children:[(0,X.jsx)(l,{size:15,"aria-hidden":`true`}),`Steps`]}),e.report&&(0,X.jsxs)(d,{size:`sm`,onClick:async()=>n(await r(e.report)),children:[(0,X.jsx)(D,{size:15,"aria-hidden":`true`}),`Report`]}),e.kind===`desktop`&&e.workflow&&(0,X.jsxs)(d,{size:`sm`,onClick:()=>$(e.workflow).catch(e=>n(e.message)),children:[(0,X.jsx)(T,{size:15,"aria-hidden":`true`}),`Replay`]}),e.kind===`web`&&e.ok&&(0,X.jsxs)(d,{size:`sm`,onClick:()=>Q(e.runDir).catch(e=>n(e.message)),children:[(0,X.jsx)(N,{size:15,"aria-hidden":`true`}),`Write a test`]})]},e.runDir))})]}):null}function fe(){let[e,t]=(0,Y.useState)(null),[n,r]=(0,Y.useState)(``),[i,a]=(0,Y.useState)(!1),s=(0,Y.useCallback)(()=>{_.get().then(e=>{t(e),r(``)},e=>r(e.message))},[]);(0,Y.useEffect)(s,[s]);let c=!!e?.session&&ae.has(e.session.state);(0,Y.useEffect)(()=>{if(!c)return;let e=setInterval(s,800);return()=>clearInterval(e)},[c,s]);let l=async e=>{a(!0),r(``);try{t(await e())}catch(e){r(e.message)}finally{a(!1)}},u=e?.session;return(0,X.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,X.jsx)(x,{}),(0,X.jsxs)(`main`,{className:`mx-auto box-border flex w-full max-w-[1100px] flex-auto flex-col gap-5 px-6 pt-10 pb-10`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,X.jsx)(y,{icon:o,size:`lg`}),(0,X.jsx)(`h1`,{className:`m-0 text-[26px] font-semibold tracking-[-0.01em]`,children:`Record`})]}),(0,X.jsx)(`p`,{className:`m-0 max-w-[70ch] text-sm leading-relaxed text-muted`,children:`Do the steps of a test yourself, in a browser or a Windows desktop app ForgeQE opens. Each click, entry and choice is recorded in order, with the checks you add. A web recording becomes a test in your repository through a chat; a desktop one is a workflow that replays with no model.`}),n&&(0,X.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:n}),!e&&!n&&(0,X.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),e&&u&&c&&(0,X.jsx)(ce,{s:u,busy:i,send:e=>void l(()=>_.command(e))}),e&&!c&&(0,X.jsxs)(X.Fragment,{children:[u?.result&&(0,X.jsx)(le,{s:u}),(0,X.jsx)(ue,{view:e,busy:i,onStart:e=>void l(()=>_.start(e))}),(0,X.jsx)(de,{rows:e.recordings})]})]})]})}export{fe as Record};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{$ as e,I as t,J as n,K as r,N as i,Q as a,R as o,Vt as s,Y as c,Z as l,bt as u,en as d,fn as f,it as p,ln as m,mt as h,p as g,pt as _,q as v,r as y,t as b}from"./status-xNQO8J6U.js";import{t as x}from"./external-link-D2pA4PJ0.js";import{t as S}from"./sticky-note-BuQrlbjE.js";import{h as C}from"./index-DuYynJ55.js";var w={name:`bandage`,size:24,node:[[`path`,{d:`M10 10.01h.01`,key:`1e9xi7`}],[`path`,{d:`M10 14.01h.01`,key:`ac23bv`}],[`path`,{d:`M14 10.01h.01`,key:`2wfrvf`}],[`path`,{d:`M14 14.01h.01`,key:`8tw8yn`}],[`path`,{d:`M18 6v12`,key:`1bcixs`}],[`path`,{d:`M6 6v12`,key:`vkc79e`}],[`rect`,{x:`2`,y:`6`,width:`20`,height:`12`,rx:`2`,key:`1wpnh2`}]]};w.node;var T=s(w),E={name:`flame`,size:24,node:[[`path`,{d:`M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4`,key:`1slcih`}]]};E.node;var D=s(E),O={name:`git-commit-horizontal`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}],[`line`,{x1:`3`,x2:`9`,y1:`12`,y2:`12`,key:`1dyftd`}],[`line`,{x1:`15`,x2:`21`,y1:`12`,y2:`12`,key:`oup4p8`}]],aliases:[`git-commit`]};O.node;var k=s(O),A={name:`hammer`,size:24,node:[[`path`,{d:`m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9`,key:`1hayfq`}],[`path`,{d:`m18 15 4-4`,key:`16gjal`}],[`path`,{d:`m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5`,key:`15ts47`}]]};A.node;var j=s(A),M=f(m(),1),N=l(),P={linked:{label:`Linked test case`,tone:`pass`,help:`It automates a test case that tests a changed work item`},changed:{label:`Test code changed`,tone:`running`,help:`The change is in test code it uses`},covers:{label:`Matches a change`,tone:`neutral`,help:`The change's words name what it does`},risk:{label:`Risk area`,tone:`warn`,help:`The release touches an area with defects or failures before`},smoke:{label:`Smoke`,tone:`neutral`,help:`Tagged smoke: in every pack`}},F={heal:{label:`Heal`,tone:`warn`,does:`An element it uses is gone: the healing agent re-runs the flow and updates the test.`},check:{label:`AI re-run decides`,tone:`warn`,does:`The healing agent re-runs the flow: it heals the test when the flow works, and reports an app bug when it fails at the same step.`},flaky:{label:`Flaky`,tone:`neutral`,does:`Passed when run again: quarantine it, or fix the cause it flakes on. Not healed.`},environment:{label:`Environment`,tone:`neutral`,does:`Network, a server error, sign-in: run again once the environment works. No heal, no bug.`},test_code:{label:`Test code broken`,tone:`fail`,does:`A missing module, a compile error, a missing fixture: fix the test's code.`}},I={work_item:C,pr:u,commit:k,note:S},L=e=>new Date(e).toLocaleString([],{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`}),R=e=>e?e.status===`passed`?`pass`:e.status===`failed`?`fail`:`warn`:`neutral`,z=e=>e<60?`${Math.round(e)}s`:`${Math.floor(e/60)}m ${Math.round(e%60)}s`,B=e=>e&&/^https?:\/\//i.test(e)?e:void 0;function V({job:e,onStop:t}){let n=(0,M.useRef)(null),[,r]=(0,M.useState)(0);(0,M.useEffect)(()=>{if(!e.running)return;let t=setInterval(()=>r(e=>e+1),1e3);return()=>clearInterval(t)},[e.running]),(0,M.useEffect)(()=>{n.current&&(n.current.scrollTop=n.current.scrollHeight)},[e.lines.length]);let i=e.running?e.kind===`build`?`Building the pack`:e.kind===`run`?`Running ${e.pack}`:`Healing ${e.pack}'s failures`:e.kind===`build`?`Built ${e.pack||`the pack`}`:e.kind===`run`?`Ran ${e.pack}`:`Healed ${e.pack}'s failures`,a=Math.round(((e.endedAt?Date.parse(e.endedAt):Date.now())-Date.parse(e.startedAt))/1e3);return(0,N.jsxs)(`section`,{"aria-label":i,className:`flex flex-col gap-2 rounded-[14px] border border-line-soft p-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(`span`,{className:`flex-1 font-medium`,children:i}),(0,N.jsx)(b,{orb:e.kind===`build`?`handing`:e.kind===`heal`?`retrying`:`working`,tone:e.running?`running`:e.exitCode===0?`pass`:e.kind===`run`&&e.exitCode===1?`warn`:`fail`,children:e.running?`Working`:e.exitCode===0?`Done`:e.kind===`run`&&e.exitCode===1?`Tests failed`:`Did not finish`}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted tabular-nums`,children:z(a)}),e.running&&(0,N.jsxs)(c,{onClick:t,className:`border-fail text-fail hover:bg-fail-soft`,children:[(0,N.jsx)(p,{size:14,fill:`currentColor`,"aria-hidden":`true`}),`Stop`]})]}),(0,N.jsx)(`code`,{className:`font-mono text-[12px] text-muted [overflow-wrap:anywhere]`,children:e.command}),(0,N.jsxs)(`details`,{open:e.running,children:[(0,N.jsxs)(`summary`,{className:`cursor-pointer text-sm text-muted`,children:[`Output (`,e.lines.length,` lines)`]}),(0,N.jsx)(`pre`,{ref:n,className:`mt-2 max-h-[300px] overflow-auto rounded-[10px] bg-surface-muted p-3 font-mono text-[12px] leading-relaxed whitespace-pre-wrap text-ink-2`,children:e.lines.join(`
|
|
2
|
-
`)||`Starting…`})]})]})}function H({title:e,aside:t,children:n}){return(0,N.jsxs)(`section`,{className:`flex flex-col gap-2`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,N.jsx)(`h3`,{className:`m-0 flex-1 text-base font-semibold`,children:e}),t]}),n]})}function U(e){let[t,n]=e.slice(-2).length===2?e.slice(-2):[void 0,e.at(-1)];return!n||!t?{fresh:[],fixed:[]}:{fresh:n.failed.filter(e=>!t.failed.includes(e)),fixed:t.failed.filter(e=>!n.failed.includes(e))}}function W({name:e,busy:t,act:n,version:r}){let[i,o]=(0,M.useState)(null),[s,l]=(0,M.useState)(``),[u,f]=(0,M.useState)(`all`),[p,m]=(0,M.useState)(null),[h,v]=(0,M.useState)(new Set);if((0,M.useEffect)(()=>{let t=!1;return d.detail(e).then(e=>!t&&(o(e),l(``)),e=>!t&&l(e.message)),()=>{t=!0}},[e,r]),(0,M.useEffect)(()=>{f(`all`),m(null),v(new Set)},[e]),s)return(0,N.jsx)(`p`,{className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:s});if(!i)return(0,N.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Loading…`});let y=i.runs.at(-1),{fresh:C,fixed:w}=U(i.runs),E=i.tests.filter(e=>u===`all`||e.reasons.some(e=>e.kind===u)),O=(i.triage?.items??[]).filter(e=>e.route===`heal`||e.route===`check`),k=Object.keys(F).filter(e=>i.triage?.items.some(t=>t.route===e)),A=Object.keys(P).filter(e=>i.tests.some(t=>t.reasons.some(t=>t.kind===e)));return(0,N.jsxs)(`section`,{"aria-labelledby":`pack-h`,className:`flex min-w-0 flex-1 flex-col gap-6`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-start gap-3`,children:[(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-1`,children:[(0,N.jsx)(`h2`,{id:`pack-h`,className:`m-0 text-[22px] font-semibold tracking-[-0.01em] [overflow-wrap:anywhere]`,children:i.name}),(0,N.jsxs)(`span`,{className:`text-sm text-muted`,children:[`Built `,L(i.createdAt)]}),i.scope.length>0&&(0,N.jsx)(`span`,{className:`flex flex-wrap gap-1.5 pt-1`,children:i.scope.map(e=>(0,N.jsx)(`span`,{className:`rounded-full bg-surface-strong px-2.5 py-0.5 text-[12px] text-ink-2`,children:e},e))})]}),p?(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 rounded-[12px] bg-accent-soft px-3 py-2`,children:[(0,N.jsxs)(`span`,{className:`text-sm`,children:[`Run `,i.tests.length,` test`,i.tests.length===1?``:`s`,` `,p===`local`?`on this machine`:`on TestMu AI`,`?`]}),(0,N.jsx)(c,{variant:`primary`,disabled:t,onClick:()=>{m(null),n(()=>d.run(i.name,p))},children:`Run`}),(0,N.jsx)(c,{onClick:()=>m(null),children:`Don't run`})]}):(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsxs)(c,{variant:`primary`,disabled:t||!i.tests.length,onClick:()=>m(`local`),children:[(0,N.jsx)(_,{size:16,"aria-hidden":`true`}),`Run here`]}),(0,N.jsx)(c,{disabled:t||!i.tests.length,onClick:()=>m(`testmu`),children:`Run on TestMu AI`})]})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,N.jsx)(g,{label:`Tests`,value:String(i.tests.length),note:A.map(e=>`${i.tests.filter(t=>t.reasons.some(t=>t.kind===e)).length} ${P[e].label.toLowerCase()}`).join(` · `)}),(0,N.jsx)(g,{label:`Not covered`,value:String(i.uncovered.length),note:`changes no test is in for`}),(0,N.jsx)(g,{label:`Risk areas`,value:String(i.risk.length)}),(0,N.jsx)(g,{label:`Last run`,value:y?y.status===`passed`?`Passed`:`${y.counts.failed} failed`:`–`,note:y?`${L(y.at)} · ${y.on===`testmu`?`TestMu AI`:y.on===`pipeline`?`pipeline`:`this machine`}`:`Not run yet`})]}),i.triage&&(0,N.jsxs)(H,{title:`Triage of the last run`,aside:(0,N.jsxs)(`span`,{className:`text-[13px] text-muted`,children:[i.triage.items.length,` failed or flaky`]}),children:[i.triage.environmentDown&&(0,N.jsx)(`p`,{className:`m-0 rounded-[12px] bg-warn-soft px-3 py-2 text-sm text-warn`,children:`Most failures were the environment: run the pack again before healing anything.`}),k.map(e=>(0,N.jsxs)(`div`,{className:`flex flex-col gap-1 rounded-[12px] border border-line-soft px-4 py-3`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsx)(b,{tone:F[e].tone,children:F[e].label}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:F[e].does})]}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:i.triage.items.filter(t=>t.route===e).map(t=>(0,N.jsxs)(`li`,{className:`flex items-start gap-3 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(e===`heal`||e===`check`)&&(0,N.jsx)(`input`,{type:`checkbox`,"aria-label":`Heal ${t.name}`,checked:h.has(t.name),onChange:e=>{let n=new Set(h);e.target.checked?n.add(t.name):n.delete(t.name),v(n)},className:`mt-1 size-5 accent-accent`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:t.name}),(0,N.jsxs)(`span`,{className:`text-[13px] text-muted [overflow-wrap:anywhere]`,children:[t.why,` · `,t.confidence,` confidence`,t.file?` · ${t.file}`:``,t.history?` · ${t.history}`:``]})]})]},t.name))})]},e)),O.length>0&&(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsxs)(c,{disabled:t||!h.size,onClick:()=>n(()=>d.heal(i.name,[...h])),children:[(0,N.jsx)(T,{size:16,"aria-hidden":`true`}),`Heal `,h.size||``,` selected`]}),(0,N.jsxs)(c,{variant:`ghost`,disabled:t,onClick:()=>v(new Set(O.map(e=>e.name))),children:[`Select all `,O.length]}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:`The healing agent re-runs each flow in the browser before it changes anything.`})]})]}),i.runs.length>0&&(0,N.jsxs)(H,{title:`Runs`,aside:C.length||w.length?(0,N.jsxs)(`span`,{className:`text-[13px] text-muted`,children:[[C.length?`${C.length} newly failing`:``,w.length?`${w.length} fixed`:``].filter(Boolean).join(` · `),` since the run before`]}):void 0,children:[(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:[...i.runs].reverse().map((e,t)=>(0,N.jsxs)(`li`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsx)(b,{tone:R(e),children:e.status===`passed`?`Passed`:e.status===`failed`?`Failed`:e.status}),(0,N.jsxs)(`span`,{className:`flex-1`,children:[L(e.at),` · `,e.on===`testmu`?`TestMu AI`:e.on===`pipeline`?`pipeline`:`this machine`]}),(0,N.jsxs)(`span`,{className:`text-muted tabular-nums`,children:[e.counts.passed,` passed · `,e.counts.failed,` failed`,e.counts.skipped?` · ${e.counts.skipped} skipped`:``,` · `,z(e.seconds)]}),B(e.url)&&(0,N.jsxs)(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1`,children:[`Pipeline `,(0,N.jsx)(x,{size:13,"aria-hidden":`true`})]})]},`${e.at}-${t}`))}),C.length>0&&(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-fail`,children:[`Newly failing: `,C.join(`, `)]}),w.length>0&&(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-pass`,children:[`Fixed: `,w.join(`, `)]})]}),(0,N.jsxs)(H,{title:`Tests (${i.tests.length})`,aside:(0,N.jsx)(`div`,{role:`group`,"aria-label":`Why in`,className:`flex flex-wrap gap-1`,children:[`all`,...A].map(e=>(0,N.jsx)(`button`,{type:`button`,"aria-pressed":u===e,title:P[e]?.help,onClick:()=>f(e),className:a(`min-h-8 cursor-pointer rounded-full border px-3 text-[13px]`,u===e?`border-ink bg-ink text-bg`:`border-line-soft bg-bg text-ink hover:bg-surface-muted`),children:e===`all`?`All`:P[e].label},e))}),children:[(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:E.slice(0,300).map(e=>(0,N.jsxs)(`li`,{className:`flex flex-col gap-1 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsxs)(`span`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsx)(`span`,{className:`font-medium [overflow-wrap:anywhere]`,children:e.test}),e.flaky&&(0,N.jsx)(b,{tone:`warn`,children:`Flaky`})]}),(0,N.jsxs)(`span`,{className:`font-mono text-[12px] text-muted [overflow-wrap:anywhere]`,children:[e.file,e.line?`:${e.line}`:``]}),(0,N.jsx)(`span`,{className:`flex flex-wrap gap-1.5`,children:e.reasons.map((e,t)=>(0,N.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-[13px] text-ink-2`,children:[(0,N.jsx)(b,{tone:P[e.kind]?.tone??`neutral`,icon:!1,children:P[e.kind]?.label??e.kind}),e.text]},t))})]},`${e.file}:${e.test}`))}),E.length>300&&(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[`The first 300 of `,E.length,`.`]})]}),i.uncovered.length>0&&(0,N.jsx)(H,{title:`Not covered (${i.uncovered.length})`,aside:(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:`Extend the closest test rather than write a new one`}),children:(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:i.uncovered.map(e=>(0,N.jsxs)(`li`,{className:`flex flex-col gap-0.5 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsxs)(`span`,{className:`[overflow-wrap:anywhere]`,children:[(0,N.jsx)(`span`,{className:`mr-1.5 font-mono text-[12px] text-muted`,children:e.item}),e.title]}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:e.why}),e.nearest&&(0,N.jsxs)(`span`,{className:`text-[13px] text-ink-2 [overflow-wrap:anywhere]`,children:[`Closest: `,e.nearest.test,` `,(0,N.jsxs)(`span`,{className:`font-mono text-[12px] text-muted`,children:[`(`,e.nearest.file,`)`]}),e.nearest.lacks.length?`, lacks ${e.nearest.lacks.join(`, `)}`:``]})]},e.item))})}),i.risk.length>0&&(0,N.jsx)(H,{title:`Risk areas`,children:(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:i.risk.map(e=>(0,N.jsxs)(`li`,{className:`flex items-start gap-3 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsx)(D,{size:16,"aria-hidden":`true`,className:a(`mt-0.5 flex-none`,e.level===`high`?`text-fail`:`text-warn`)}),(0,N.jsxs)(`span`,{className:`flex flex-col`,children:[(0,N.jsxs)(`span`,{children:[e.area,` `,(0,N.jsxs)(`span`,{className:`text-muted`,children:[`· `,e.level]})]}),(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:e.reasons.join(`; `)})]})]},e.area))})}),(0,N.jsx)(H,{title:`Changes (${i.items.length})`,children:(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:i.items.slice(0,200).map(e=>{let t=I[e.kind]||S;return(0,N.jsxs)(`li`,{className:`flex items-start gap-3 border-t border-line-soft py-2 text-sm first:border-t-0`,children:[(0,N.jsx)(t,{size:16,"aria-hidden":`true`,className:`mt-0.5 flex-none text-muted`}),(0,N.jsxs)(`span`,{className:`min-w-0 flex-1 [overflow-wrap:anywhere]`,children:[(0,N.jsxs)(`span`,{className:`mr-1.5 font-mono text-[12px] text-muted`,children:[e.type?`${e.type} `:``,e.id]}),e.title]}),B(e.url)&&(0,N.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,"aria-label":`Open ${e.id}`,className:`flex-none`,children:(0,N.jsx)(x,{size:14,"aria-hidden":`true`})})]},`${e.kind}-${e.id}`)})})}),i.notes.length>0&&(0,N.jsx)(`ul`,{className:`m-0 flex flex-col gap-1 pl-5 text-[13px] text-muted`,children:i.notes.map((e,t)=>(0,N.jsx)(`li`,{children:e},t))})]})}function G({open:e,onClose:n,view:s,onBuild:l,busy:u}){let[d,f]=(0,M.useState)({rangeRepo:`product`,prRepo:`product`,risk:!0,smoke:!0});(0,M.useEffect)(()=>{e&&f({rangeRepo:s.productRepo?`product`:`tests`,prRepo:s.productRepo?`product`:`tests`,risk:!0,smoke:!0})},[e,s.productRepo]);let p=(e,t)=>f({...d,[e]:t}),m=(e,t,n,r)=>(0,N.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,N.jsx)(`label`,{htmlFor:`pk-${e}`,className:`text-sm font-medium`,children:t}),(0,N.jsx)(i,{id:`pk-${e}`,value:String(d[e]??``),spellCheck:!1,maxLength:200,placeholder:n,onChange:t=>p(e,t.target.value)}),r&&(0,N.jsx)(`span`,{className:`text-[13px] text-muted`,children:r})]}),h=(e,t)=>(0,N.jsxs)(`fieldset`,{className:`m-0 flex flex-wrap items-center gap-x-4 gap-y-1 border-0 p-0`,children:[(0,N.jsx)(`legend`,{className:`mb-1 text-[13px] text-muted`,children:t}),(0,N.jsxs)(`label`,{className:`flex min-h-9 cursor-pointer items-center gap-2 text-sm`,children:[(0,N.jsx)(`input`,{type:`radio`,name:e,checked:d[e]===`product`,disabled:!s.productRepo,onChange:()=>p(e,`product`),className:`size-4 accent-accent`}),`The product's `,s.productRepo?(0,N.jsx)(`code`,{className:`font-mono text-[12px]`,children:s.productRepo}):(0,N.jsx)(`span`,{className:`text-muted`,children:`(set defects.product_repo)`})]}),(0,N.jsxs)(`label`,{className:`flex min-h-9 cursor-pointer items-center gap-2 text-sm`,children:[(0,N.jsx)(`input`,{type:`radio`,name:e,checked:d[e]===`tests`,onChange:()=>p(e,`tests`),className:`size-4 accent-accent`}),`The tests' `,s.repo===`.`?`(this project)`:(0,N.jsx)(`code`,{className:`font-mono text-[12px]`,children:s.repo})]})]}),g=`flex flex-col gap-3 rounded-[12px] border border-line-soft p-3`;return(0,N.jsx)(t,{open:e,onClose:n,wide:!0,title:`Build a regression pack`,description:`The tests a release's changes can break, from any mix of the changes below. Building runs nothing; it takes seconds.`,footer:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(c,{onClick:n,children:`Cancel`}),(0,N.jsxs)(c,{variant:`primary`,disabled:u,onClick:()=>l(d),children:[(0,N.jsx)(j,{size:16,"aria-hidden":`true`}),`Build the pack`]})]}),children:(0,N.jsxs)(`div`,{className:`flex flex-col gap-4 pt-3`,children:[m(`name`,`Name`,`release-1.5`,`Lower-case letters, digits, dots and dashes. Empty: release-<date>.`),(0,N.jsxs)(`div`,{className:g,children:[(0,N.jsxs)(`h3`,{className:`m-0 flex items-center gap-2 text-sm font-semibold`,children:[(0,N.jsx)(k,{size:16,"aria-hidden":`true`,className:`text-accent`}),`Code changes`]}),(0,N.jsxs)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-3`,children:[m(`from`,`Commits after`,`release/1.4, a tag or a commit`),m(`to`,`Up to`,`HEAD`)]}),h(`rangeRepo`,`In the repository`),(0,N.jsxs)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-3`,children:[m(`prs`,`Pull requests`,`57, 58 or their links`),(0,N.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,N.jsx)(`label`,{htmlFor:`pk-days`,className:`text-sm font-medium`,children:`Or merged in the last`}),(0,N.jsxs)(`span`,{className:`flex items-center gap-2 text-sm`,children:[(0,N.jsx)(i,{id:`pk-days`,type:`number`,min:1,max:365,value:d.mergedDays??``,onChange:e=>p(`mergedDays`,e.target.value?Number(e.target.value):void 0),className:`w-24`}),` days`]})]})]}),(d.prs||d.mergedDays)&&h(`prRepo`,`Pull requests of`)]}),(0,N.jsxs)(`div`,{className:a(g,!s.azureDevops&&`opacity-70`),children:[(0,N.jsxs)(`h3`,{className:`m-0 flex items-center gap-2 text-sm font-semibold`,children:[(0,N.jsx)(C,{size:16,"aria-hidden":`true`,className:`text-accent`}),`Azure DevOps work items and their linked test cases`]}),!s.azureDevops&&(0,N.jsxs)(`p`,{className:`m-0 text-[13px] text-muted`,children:[`Not set up: `,(0,N.jsx)(`a`,{href:o(`settings`,`integrations`),children:`Settings, Integrations`}),`.`]}),(0,N.jsxs)(`div`,{className:`grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))] gap-3`,children:[m(`sprint`,`Sprint`,`current, or Sprint 41`),m(`iteration`,`Iteration path`,`Shop\\Release 2026.09`),m(`area`,`Area path`,`Shop\\Checkout`),m(`parent`,`Epic or feature`,`1200`),m(`workItems`,`Work items`,`2211, 2212`)]}),(0,N.jsx)(`p`,{className:`m-0 text-[13px] text-muted`,children:`Their stories and bugs, the test cases each is tested by, and the files their linked pull requests changed.`})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-x-6 gap-y-2`,children:[(0,N.jsxs)(`span`,{className:`flex items-center gap-2 text-sm`,children:[(0,N.jsx)(r,{checked:d.risk!==!1,onChange:e=>p(`risk`,e),label:`Add tests for risk areas`}),`Add tests for risk areas the release touches`]}),(0,N.jsxs)(`span`,{className:`flex items-center gap-2 text-sm`,children:[(0,N.jsx)(r,{checked:d.smoke!==!1,onChange:e=>p(`smoke`,e),label:`Add smoke tests`}),`Add smoke-tagged tests`]})]})]})})}function K({sub:t}){let[r,i]=(0,M.useState)(null),[s,l]=(0,M.useState)(``),[u,f]=(0,M.useState)(!1),[p,m]=(0,M.useState)(!1),g=(0,M.useCallback)(()=>{d.list().then(e=>{i(e),l(``)},e=>l(e.message))},[]);(0,M.useEffect)(g,[g]);let _=!!r?.job?.running;(0,M.useEffect)(()=>{if(!_)return;let e=setInterval(g,1500);return()=>clearInterval(e)},[_,g]);let b=async e=>{f(!0),l(``);try{await e(),g()}catch(e){l(e.message)}finally{f(!1)}},x=t?decodeURIComponent(t):``,S=r?.packs.find(e=>e.name===x)||r?.packs[0],C=(0,M.useMemo)(()=>`${r?.job?.endedAt??``}|${S?.runs??0}|${S?.createdAt??``}`,[r,S]);return(0,N.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,N.jsx)(y,{}),(0,N.jsxs)(`main`,{className:`@container mx-auto box-border flex w-full max-w-[1180px] flex-auto flex-col gap-4 px-6 pt-10 pb-10`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,N.jsx)(v,{icon:h,size:`lg`}),(0,N.jsx)(`h1`,{className:`m-0 flex-1 text-[26px] font-semibold tracking-[-0.01em]`,children:`Regression`}),(0,N.jsxs)(c,{variant:`primary`,disabled:!r||_,onClick:()=>m(!0),children:[(0,N.jsx)(j,{size:16,"aria-hidden":`true`}),`Build a pack`]})]}),(0,N.jsxs)(`p`,{className:`m-0 max-w-[74ch] text-sm leading-relaxed text-muted`,children:[`A regression pack is the set of tests in `,r&&r.repo!==`.`?(0,N.jsx)(`code`,{className:`font-mono text-[13px]`,children:r.repo}):`this project`,` that a release's changes can break: from the commits and pull requests of the product or development repositories, and the Azure DevOps sprint, epic or work items with their linked test cases. Each test says why it is in; the changes no test covers are listed. Run it here or on TestMu AI, and each run is triaged into what to heal, re-run or fix.`]}),s&&(0,N.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:s}),!r&&!s&&(0,N.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),r?.job&&(0,N.jsx)(V,{job:r.job,onStop:()=>b(()=>d.stop())}),r&&(r.packs.length?(0,N.jsxs)(`div`,{className:`flex flex-col gap-6 @2xl:flex-row @2xl:items-start @2xl:gap-8`,children:[(0,N.jsxs)(`nav`,{"aria-label":`Packs`,className:`flex min-w-0 flex-col gap-1 @2xl:sticky @2xl:top-6 @2xl:w-[250px] @2xl:flex-none`,children:[(0,N.jsxs)(`span`,{className:`px-3 text-[13px] font-medium text-muted`,children:[`Packs (`,r.packs.length,`)`]}),(0,N.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:r.packs.map(t=>(0,N.jsx)(`li`,{children:(0,N.jsxs)(`a`,{href:o(`regression`,encodeURIComponent(t.name)),"aria-current":S?.name===t.name?`page`:void 0,className:a(`flex min-h-[60px] items-center gap-3 rounded-[12px] px-3 py-2 text-ink no-underline`,S?.name===t.name?`bg-surface-strong hover:text-ink`:`hover:bg-surface-muted hover:text-ink`),children:[r?.job?.running&&r.job.pack===t.name?(0,N.jsx)(n,{state:r.job.kind===`heal`?`retrying`:`working`,label:`Working on it`,px:16}):(0,N.jsx)(`span`,{className:a(`size-2.5 flex-none rounded-full`,t.lastRun?t.lastRun.status===`passed`?`bg-pass`:`bg-fail`:`bg-line`),"aria-label":t.lastRun?t.lastRun.status:`not run`}),(0,N.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,N.jsx)(`span`,{className:`truncate text-[15px] font-medium`,children:t.name}),(0,N.jsxs)(`span`,{className:`truncate text-[13px] text-muted`,children:[e(t.tests,`test`),` · `,t.uncovered,` not covered · `,L(t.createdAt)]})]})]})},t.name))})]}),S&&(0,N.jsx)(W,{name:S.name,busy:u||_,act:b,version:C})]}):(0,N.jsxs)(`div`,{className:`flex flex-col items-start gap-3 rounded-[18px] border border-line p-6`,children:[(0,N.jsx)(h,{size:24,"aria-hidden":`true`,className:`text-muted`}),(0,N.jsx)(`p`,{className:`m-0 max-w-[62ch] leading-relaxed text-ink-2`,children:`No regression packs yet. Build one from a sprint, the commits since the last release, or the pull requests merged this week.`}),(0,N.jsx)(c,{onClick:()=>m(!0),children:`Build a pack`})]}))]}),r&&(0,N.jsx)(G,{open:p,onClose:()=>m(!1),view:r,busy:u||_,onBuild:e=>b(async()=>{await d.build(e),m(!1)})})]})}export{K as Regression};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{$ as e,At as t,Ft as n,J as r,L as i,Mt as a,N as o,Ot as s,P as c,Q as l,R as u,Tt as d,Vt as f,Y as p,Z as m,_ as h,fn as g,in as _,ln as v,p as y,pt as b,q as x,qt as S,r as C,t as w,y as T}from"./status-xNQO8J6U.js";import{t as E}from"./circle-dashed-zjN_W6rR.js";import{n as D,t as O}from"./markdown-B1Rz6VFK.js";import{t as k}from"./external-link-D2pA4PJ0.js";import{A,P as j,b as M,w as N}from"./index-DuYynJ55.js";import{n as P,t as F}from"./when-CHnpLdYw.js";var I={name:`percent`,size:24,node:[[`line`,{x1:`19`,x2:`5`,y1:`5`,y2:`19`,key:`1x9vlm`}],[`circle`,{cx:`6.5`,cy:`6.5`,r:`2.5`,key:`4mh3h7`}],[`circle`,{cx:`17.5`,cy:`17.5`,r:`2.5`,key:`1mdrzq`}]]};I.node;var L=f(I),R=g(v(),1),z=m(),B={suite:`Suite`,monitor:`Monitor round`,run:`Browser run`,explore:`Exploration`,api:`API run`,desktop:`Desktop run`,mobile:`Mobile run`,page:`Report page`},V=e=>{if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:`short`,day:`numeric`,...t.getFullYear()===new Date().getFullYear()?{}:{year:`numeric`},hour:`numeric`,minute:`2-digit`})},H=e=>{if(!e)return``;let t=Math.round(e/1e3);return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m ${t%60}s`:`${Math.floor(t/3600)}h ${Math.floor(t%3600/60)}m`},U=e=>e===`passed`,W=e=>e===`failed`||e===`error`;function G(e){return e.scope===`page`?{tone:`neutral`,label:`Report`}:e.counts.total?e.counts.failed?{tone:`fail`,label:`${e.counts.failed} failed`}:e.stopped||e.counts.other?{tone:`warn`,label:e.stopped?`Stopped`:`${e.counts.other} not run`}:{tone:`pass`,label:`Passed`}:{tone:`neutral`,label:`No results`}}var K=50;function q({r:e}){let t=G(e),n=e.scope===`page`?d:t.tone===`pass`?A:t.tone===`fail`?a:E;return(0,z.jsx)(n,{size:16,"aria-label":t.label,className:l(`flex-none`,t.tone===`pass`?`text-pass`:t.tone===`fail`?`text-fail`:t.tone===`warn`?`text-warn`:`text-muted`)})}function J(t){let n=t.counts,r=H(t.ms)?` in ${H(t.ms)}`:``;return n.total?n.failed?`${n.failed} of ${e(n.total,`case`)} failed${n.passed?`, ${n.passed} passed`:``}${n.other?`, ${n.other} did not run`:``}${r}.`:n.other?`${n.passed} of ${e(n.total,`case`)} passed; ${n.other} did not run${t.stopped?` because it was stopped`:``}.`:n.total===1?`Its case passed${r}.`:`All ${n.total} cases passed${r}.`:t.stopped?`It stopped before any case ran.`:`It has no results.`}function Y({counts:e}){let t=[{n:e.passed,label:`passed`,cls:`bg-pass`},{n:e.failed,label:`failed`,cls:`bg-fail`},{n:e.other,label:`other`,cls:`bg-line`}].filter(e=>e.n>0);return(0,z.jsxs)(`div`,{role:`img`,"aria-label":`${e.passed} passed, ${e.failed} failed, ${e.other} other, of ${e.total}`,className:`flex flex-col gap-1.5`,children:[(0,z.jsx)(`div`,{className:`flex h-3 w-full overflow-hidden rounded-full bg-surface-strong`,children:t.map(t=>(0,z.jsx)(`span`,{className:t.cls,style:{width:`${t.n/Math.max(1,e.total)*100}%`}},t.label))}),(0,z.jsx)(`div`,{"aria-hidden":`true`,className:`flex flex-wrap gap-x-4 text-[13px] text-muted`,children:t.map(e=>(0,z.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,z.jsx)(`span`,{className:l(`size-2 rounded-full`,e.cls)}),e.n,` `,e.label]},e.label))})]})}function X({runs:e}){let t=e.map(e=>({at:e.startedAt,rate:e.counts.total?Math.round(e.counts.passed/e.counts.total*100):0}));return(0,z.jsx)(`div`,{role:`img`,"aria-label":`Pass rate of the last ${t.length} runs, oldest first: ${t.map(e=>`${e.rate}%`).join(`, `)}`,className:`flex h-[96px] max-w-[520px] items-end gap-2 border-b border-line pb-1`,children:t.map((e,n)=>(0,z.jsxs)(`div`,{className:`flex h-full min-w-0 flex-1 flex-col items-center justify-end gap-1`,title:`${V(e.at)}: ${e.rate}%`,children:[(0,z.jsxs)(`span`,{className:`text-[12px] text-ink-2 tabular-nums`,children:[e.rate,`%`]}),(0,z.jsx)(`span`,{className:l(`w-full max-w-[44px] rounded-t-[6px]`,n===t.length-1?`bg-accent`:`bg-[#dbe1fe]`),style:{height:`${Math.max(2,e.rate)}%`}})]},n))})}function Z({c:e,open:t,onToggle:r}){let i=U(e.status)?`pass`:W(e.status)?`fail`:`neutral`;return(0,z.jsxs)(`li`,{className:`border-t border-line-soft`,children:[(0,z.jsxs)(`button`,{type:`button`,"aria-expanded":t,onClick:r,className:`grid min-h-11 w-full cursor-pointer grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-3 border-0 bg-transparent px-2 py-1.5 text-left text-ink hover:bg-surface-muted`,children:[i===`pass`?(0,z.jsx)(A,{size:16,"aria-label":e.status,className:`text-pass`}):i===`fail`?(0,z.jsx)(a,{size:16,"aria-label":e.status,className:`text-fail`}):(0,z.jsx)(E,{size:16,"aria-label":e.status,className:`text-muted`}),(0,z.jsxs)(`span`,{className:`truncate text-[14px]`,children:[(0,z.jsx)(`span`,{className:`font-mono text-[12.5px] text-ink-2`,children:e.id}),` `,e.title]}),(0,z.jsx)(`span`,{className:`text-[12.5px] text-muted tabular-nums`,children:[e.device,H(e.ms)].filter(Boolean).join(` · `)}),(0,z.jsx)(n,{size:16,"aria-hidden":`true`,className:l(`flex-none text-muted transition-transform`,t&&`rotate-180`)})]}),t&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-2 px-2 pb-3 pl-9`,children:[e.tokens>0&&(0,z.jsxs)(`span`,{className:`text-[12.5px] text-muted`,children:[T(e.tokens),` tokens`]}),e.summary&&(0,z.jsx)(D,{text:e.summary,className:`text-sm`}),(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1 text-[13px] text-muted`,children:[e.defect&&(0,z.jsxs)(`span`,{children:[`Defect: `,e.defect]}),e.bug&&(0,z.jsx)(D,{text:e.bug.url?`Bug: [${e.bug.label.replace(/[[\]]/g,``)}](${e.bug.url})`:`Bug: ${e.bug.label}`,className:`text-[13px] text-muted`}),e.testFile&&(0,z.jsxs)(`span`,{children:[`Test: `,(0,z.jsx)(O,{path:e.testFile})]}),e.runDir&&(0,z.jsxs)(`span`,{children:[`Run: `,(0,z.jsx)(O,{path:e.runDir})]}),e.url&&(0,z.jsx)(D,{text:`[Open the case](${e.url})`,className:`text-[13px]`})]})]})]})}function Q({run:e,history:t}){let[n,r]=(0,R.useState)(null),[a,o]=(0,R.useState)(!1),[s,c]=(0,R.useState)(``),[d,f]=(0,R.useState)(``),[m,g]=(0,R.useState)(!1);(0,R.useEffect)(()=>{r(null),c(``),o(!1)},[e.key]);let _=G(e),v=e.scope===`page`,y=(0,R.useMemo)(()=>{let t=e=>W(e.status)?0:U(e.status)?2:1;return e.cases.map((e,t)=>({c:e,i:t})).sort((e,n)=>t(e.c)-t(n.c)||e.i-n.i)},[e]),b=y.filter(({c:e})=>!U(e.status)).length,x=a?y.filter(({c:e})=>!U(e.status)):y,C=async()=>{if(d.trim()&&!m){g(!0);try{let{id:t}=await S.start(`About the ${B[e.scope].toLowerCase()} report "${e.title}" in \`${e.folder}\` (${V(e.startedAt)}): ${d.trim()}`,{});location.hash=u(`chats`,t)}catch(e){c(e.message),g(!1)}}};return(0,z.jsxs)(`section`,{"aria-labelledby":`report-h`,className:`flex min-w-0 flex-1 flex-col gap-5`,children:[(0,z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1`,children:[(0,z.jsx)(`h2`,{id:`report-h`,className:`m-0 min-w-0 text-[22px] font-semibold tracking-[-0.01em] [overflow-wrap:anywhere]`,children:e.title}),(0,z.jsx)(w,{tone:_.tone===`warn`?`warn`:_.tone,children:_.label})]}),(0,z.jsx)(`span`,{className:`text-sm text-muted`,children:[B[e.scope],V(e.startedAt),e.tokens?`${T(e.tokens)} tokens`:``,e.cost?h(e.cost.amount,e.cost.currency):``].filter(Boolean).join(` · `)})]}),(0,z.jsxs)(`div`,{className:l(`flex flex-col gap-3 rounded-[14px] px-4 py-3`,v?`bg-surface-muted`:_.tone===`fail`?`bg-fail-soft`:_.tone===`pass`?`bg-pass-soft`:`bg-surface-muted`),children:[(0,z.jsx)(`p`,{className:`m-0 text-[15px] leading-relaxed text-ink`,children:v?`A report page ForgeQE wrote (a readiness review, results imported from a test framework, …). Its details are in the page itself.`:J(e)}),!v&&e.counts.total>1&&(0,z.jsx)(Y,{counts:e.counts}),(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[e.report&&(0,z.jsxs)(p,{variant:`primary`,size:`sm`,onClick:async()=>c(await i(e.report)),children:[(0,z.jsx)(k,{size:15,"aria-hidden":`true`}),`Open full report`]}),(0,z.jsx)(O,{path:e.folder})]})]}),s&&(0,z.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:s}),!v&&e.cases.length>0&&(0,z.jsxs)(`div`,{className:`flex flex-col`,children:[(0,z.jsxs)(`div`,{className:`mb-1 flex flex-wrap items-center gap-2`,children:[(0,z.jsxs)(`h3`,{className:`m-0 flex-1 text-base font-semibold`,children:[`Cases `,(0,z.jsx)(`span`,{className:`font-normal text-muted tabular-nums`,children:e.counts.total})]}),b>0&&b<y.length&&(0,z.jsx)(`div`,{className:`flex gap-1.5`,children:[[!1,`All`,y.length],[!0,`Not passed`,b]].map(([e,t,n])=>(0,z.jsxs)(`button`,{type:`button`,"aria-pressed":a===e,onClick:()=>o(e),className:l(`inline-flex min-h-7 cursor-pointer items-center gap-1 rounded-full border px-2.5 text-[12.5px] font-medium`,a===e?`border-accent bg-accent-soft text-ink`:`border-line-soft bg-bg text-muted hover:text-ink`),children:[t,` `,(0,z.jsx)(`span`,{className:`tabular-nums`,children:n})]},t))})]}),(0,z.jsxs)(`ul`,{className:`m-0 list-none p-0`,children:[x.map(({c:e,i:t})=>(0,z.jsx)(Z,{c:e,open:n===t,onToggle:()=>r(n===t?null:t)},`${e.id}-${t}`)),e.cases.length<e.counts.total&&(0,z.jsxs)(`li`,{className:`border-t border-line-soft py-3 text-sm text-muted`,children:[`The first `,e.cases.length,` of `,e.counts.total,`; the full report has them all.`]})]})]}),e.writeBack.length>0&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`Posted back`}),(0,z.jsx)(D,{text:e.writeBack.map(e=>`- ${e}`).join(`
|
|
2
|
-
`),className:`text-sm`})]}),!v&&t.length>1&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,z.jsxs)(`h3`,{className:`m-0 text-base font-semibold`,children:[`Last runs `,(0,z.jsx)(`span`,{className:`font-normal text-muted`,children:`pass rate, oldest first`})]}),(0,z.jsx)(X,{runs:t})]}),(0,z.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),C()},className:`flex items-center gap-2 rounded-full border border-line bg-bg py-1.5 pr-1.5 pl-5 shadow-composer @2xl:sticky @2xl:bottom-4`,children:[(0,z.jsx)(`label`,{htmlFor:`ask-report`,className:`sr-only`,children:`Ask about this report`}),(0,z.jsx)(`input`,{id:`ask-report`,value:d,onChange:e=>f(e.target.value),placeholder:`Ask about this report…`,className:`min-h-10 min-w-0 flex-1 border-0 bg-transparent text-[15px] text-ink outline-none placeholder:text-muted`}),(0,z.jsx)(`button`,{type:`submit`,"aria-label":`Ask`,disabled:!d.trim()||m,className:l(`inline-flex size-10 flex-none cursor-pointer items-center justify-center rounded-full border-0 disabled:cursor-not-allowed`,d.trim()?`bg-accent text-white hover:bg-accent-hover`:`bg-line text-muted`),children:(0,z.jsx)(j,{size:18,strokeWidth:2.2,"aria-hidden":`true`})})]})]})}function $({days:e}){if(!e.length)return(0,z.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`No runs with results yet.`});let t=e.slice(-14),n=e=>e.cases?Math.round(e.passed/e.cases*100):0;return(0,z.jsx)(`div`,{role:`img`,"aria-label":`Pass rate by day, oldest first: ${t.map(e=>`${e.day} ${n(e)}%`).join(`, `)}`,className:`flex h-[180px] items-end gap-1.5 border-b border-line pb-1`,children:t.map((e,r)=>(0,z.jsxs)(`div`,{className:`flex h-full min-w-0 flex-1 flex-col items-center justify-end gap-1`,title:`${e.day}: ${e.passed} of ${e.cases} passed in ${e.runs} run${e.runs===1?``:`s`}`,children:[(0,z.jsxs)(`span`,{className:`text-[11px] text-ink-2 tabular-nums`,children:[n(e),`%`]}),(0,z.jsx)(`span`,{className:l(`w-full max-w-[36px] rounded-t-[6px]`,r===t.length-1?`bg-accent`:`bg-[#dbe1fe]`),style:{height:`${Math.max(2,n(e))}%`}}),(0,z.jsx)(`span`,{className:`text-[11px] text-muted tabular-nums`,children:e.day.slice(5)})]},e.day))})}function ee({project:n,build:a,onBuilt:o}){let[s,c]=(0,R.useState)(a),[u,d]=(0,R.useState)(``),f=!!s?.running;(0,R.useEffect)(()=>{if(!f)return;let e=setInterval(async()=>{try{let e=await _.buildStatus();c(e),e&&!e.running&&o()}catch{}},1200);return()=>clearInterval(e)},[f,o]);let m=n.cases?Math.round(n.passed/n.cases*100):0;return(0,z.jsxs)(`section`,{"aria-labelledby":`project-h`,className:`flex min-w-0 flex-1 flex-col gap-6`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap items-start gap-x-4 gap-y-3`,children:[(0,z.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_300px] flex-col gap-1`,children:[(0,z.jsx)(`h2`,{id:`project-h`,className:`m-0 text-[22px] font-semibold tracking-[-0.01em]`,children:`Project report`}),(0,z.jsx)(`span`,{className:`text-sm text-muted`,children:n.runs?`Every run from ${V(n.from)} to ${V(n.to)}, taken together.`:`Every run, taken together, once there are some.`})]}),n.page&&(0,z.jsxs)(p,{variant:`primary`,onClick:async()=>d(await i(n.page.file)),children:[(0,z.jsx)(k,{size:16,"aria-hidden":`true`}),`Open project report`]}),(0,z.jsx)(p,{disabled:f,onClick:async()=>{d(``);try{c(await _.build())}catch(e){d(e.message)}},children:f?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(r,{state:`working`,px:16}),`Building…`]}):n.page?`Rebuild`:`Build project report`})]}),(0,z.jsx)(`p`,{className:`-mt-3 m-0 text-[13px] text-muted`,children:n.page?`The page was built ${V(n.page.builtAt)}, by forgeqe bi build.`:`The project report page is built by forgeqe bi build from every run; it has not been built yet.`}),u&&(0,z.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:u}),s&&(s.running||s.ok===!1||s.lines.length>0)&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[!s.running&&(0,z.jsx)(`p`,{className:l(`m-0 rounded-[12px] px-3 py-2 text-sm`,s.ok?`bg-pass-soft text-pass`:`bg-fail-soft text-fail`),children:s.ok?`The project report is built.`:`forgeqe bi build stopped with a problem; its output is below.`}),(0,z.jsx)(`pre`,{"aria-label":`forgeqe bi build output`,"aria-live":`polite`,className:`m-0 max-h-[200px] overflow-auto rounded-[12px] bg-surface-muted px-4 py-3 font-mono text-[12px] leading-relaxed whitespace-pre-wrap text-ink-2 [overflow-wrap:anywhere]`,children:s.lines.length?s.lines.join(`
|
|
3
|
-
`):`Starting…`})]}),(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,z.jsx)(y,{icon:b,label:`Runs`,value:String(n.runs)}),(0,z.jsx)(y,{icon:N,label:`Cases run`,value:String(n.cases)}),(0,z.jsx)(y,{icon:L,label:`Pass rate`,value:n.cases?`${m}%`:`–`,note:`${n.passed} passed, ${n.failed} failed`}),(0,z.jsx)(y,{icon:t,label:`Tokens`,value:T(n.tokens),note:n.cost?h(n.cost.amount,n.cost.currency):void 0})]}),(0,z.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`Pass rate by day`}),(0,z.jsx)($,{days:n.days})]}),(0,z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`Fails most`}),n.failing.length===0?(0,z.jsx)(`p`,{className:`m-0 border-t border-line-soft py-4 text-sm text-muted`,children:`No case has failed.`}):(0,z.jsx)(`ul`,{className:`m-0 list-none p-0`,children:n.failing.map(e=>(0,z.jsxs)(`li`,{className:`flex min-h-[56px] flex-wrap items-center gap-x-3 gap-y-1 border-t border-line-soft py-2`,children:[(0,z.jsxs)(`span`,{className:`flex min-w-0 flex-[1_1_260px] flex-col gap-0.5`,children:[(0,z.jsxs)(`span`,{className:`font-medium`,children:[(0,z.jsx)(`span`,{className:`font-mono text-[13px] text-ink-2`,children:e.id}),` `,e.title]}),e.summary&&(0,z.jsx)(D,{text:e.summary,className:`text-[13px] text-muted [&_p]:my-0`})]}),(0,z.jsxs)(w,{tone:`fail`,children:[e.failed,` of `,e.runs,` failed`]}),(0,z.jsxs)(`span`,{className:`text-[13px] text-muted`,children:[`last `,V(e.lastFailed)]})]},e.id||e.title))})]}),(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-x-10 gap-y-6`,children:[(0,z.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_280px] flex-col gap-1`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`Flaky`}),(0,z.jsx)(`p`,{className:`m-0 mb-1 text-[13px] text-muted`,children:`Cases that both passed and failed.`}),n.flaky.length===0?(0,z.jsx)(`p`,{className:`m-0 border-t border-line-soft py-3 text-sm text-muted`,children:`None.`}):n.flaky.map(e=>(0,z.jsxs)(`div`,{className:`flex items-center gap-3 border-t border-line-soft py-2 text-sm`,children:[(0,z.jsxs)(`span`,{className:`min-w-0 flex-1 truncate`,children:[(0,z.jsx)(`span`,{className:`font-mono text-[13px] text-ink-2`,children:e.id}),` `,e.title]}),(0,z.jsxs)(`span`,{className:`text-[13px] text-muted tabular-nums`,children:[e.failed,`/`,e.runs,` failed`]})]},e.id||e.title))]}),(0,z.jsxs)(`div`,{className:`flex min-w-0 flex-[1_1_280px] flex-col gap-1`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`Defects`}),(0,z.jsx)(`p`,{className:`m-0 mb-1 text-[13px] text-muted`,children:`Failures grouped by cause.`}),n.defects.length===0?(0,z.jsx)(`p`,{className:`m-0 border-t border-line-soft py-3 text-sm text-muted`,children:`None found.`}):n.defects.map(e=>(0,z.jsxs)(`div`,{className:`flex items-center gap-3 border-t border-line-soft py-2 text-sm`,children:[(0,z.jsx)(`span`,{className:`min-w-0 flex-1 [overflow-wrap:anywhere]`,children:e.title}),(0,z.jsxs)(`span`,{className:`text-[13px] text-muted tabular-nums`,children:[e.cases,` case`,e.cases===1?``:`s`,`, `,e.runs,` time`,e.runs===1?``:`s`]})]},e.title))]})]}),n.kinds.length>1&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,z.jsx)(`h3`,{className:`m-0 text-base font-semibold`,children:`By kind`}),n.kinds.map(t=>(0,z.jsxs)(`div`,{className:`flex items-center gap-3 border-t border-line-soft py-2 text-sm`,children:[(0,z.jsx)(`span`,{className:`flex-1`,children:B[t.scope]||t.scope}),(0,z.jsxs)(`span`,{className:`text-[13px] text-muted tabular-nums`,children:[e(t.runs,`run`),` · `,t.cases?Math.round(t.passed/t.cases*100):0,`% passed`]})]},t.scope))]})]})}function te({sub:e}){let[t,n]=(0,R.useState)(null),[r,i]=(0,R.useState)(``),[a,d]=(0,R.useState)(``),[f,m]=(0,R.useState)(``),[h,g]=(0,R.useState)(`all`),[v,y]=(0,R.useState)(K),b=(0,R.useCallback)(()=>{_.list().then(n,e=>i(e.message))},[]);(0,R.useEffect)(b,[b]);let S=e===`project`?`project`:`execution`,w=t?.rows??null,T=f.toLowerCase().split(/\s+/).filter(Boolean),E=(0,R.useMemo)(()=>(w||[]).filter(e=>(!a||e.scope===a)&&T.every(t=>`${e.title} ${e.id} ${B[e.scope]}`.toLowerCase().includes(t))),[w,a,f]),D=E.filter(e=>G(e).tone===`fail`).length,O=h===`failed`?E.filter(e=>G(e).tone===`fail`):E;(0,R.useEffect)(()=>y(K),[a,f,h]);let k=e&&S===`execution`?decodeURIComponent(e):``,A=w?.find(e=>e.key===k)||O[0],j=(0,R.useMemo)(()=>A&&w?w.filter(e=>e.scope===A.scope&&e.title===A.title&&String(e.startedAt||``)<=String(A.startedAt||``)).slice(0,10).reverse():[],[A,w]),N=[...new Set((w||[]).map(e=>e.scope))];return(0,R.useEffect)(()=>{e&&S===`execution`&&window.innerWidth<1024&&document.getElementById(`report-h`)?.scrollIntoView({block:`start`})},[e,S]),(0,z.jsxs)(`div`,{className:`flex min-h-screen flex-col`,children:[(0,z.jsx)(C,{}),(0,z.jsxs)(`main`,{className:`@container mx-auto box-border flex w-full max-w-[1180px] flex-auto flex-col gap-4 px-6 pt-10 pb-6`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap items-end gap-x-6 gap-y-2`,children:[(0,z.jsx)(x,{icon:s,size:`lg`}),(0,z.jsx)(`h1`,{className:`m-0 text-[26px] font-semibold tracking-[-0.01em]`,children:`Reports`}),(0,z.jsx)(`nav`,{"aria-label":`Reports`,className:`flex gap-1 rounded-full bg-surface-strong p-1`,children:[[`execution`,`Execution reports`,u(`reports`)],[`project`,`Project report`,u(`reports`,`project`)]].map(([e,t,n])=>(0,z.jsx)(`a`,{href:n,"aria-current":S===e?`page`:void 0,className:l(`inline-flex min-h-9 items-center rounded-full px-4 text-sm font-medium no-underline`,S===e?`bg-bg text-ink shadow-composer hover:text-ink`:`text-ink-2 hover:text-ink`),children:t},e))})]}),r&&(0,z.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail`,children:r}),!t&&!r&&(0,z.jsx)(`p`,{role:`status`,className:`m-0 text-sm text-muted`,children:`Loading…`}),t&&S===`project`&&(0,z.jsx)(ee,{project:t.project,build:t.build,onBuilt:b}),t&&S===`execution`&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-6 @2xl:flex-row @2xl:items-start @2xl:gap-8`,children:[(0,z.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2 @2xl:sticky @2xl:top-6 @2xl:w-[300px] @2xl:flex-none`,children:[(0,z.jsxs)(`div`,{className:`relative min-w-0`,children:[(0,z.jsx)(M,{size:16,"aria-hidden":`true`,className:`pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-muted`}),(0,z.jsx)(`label`,{htmlFor:`report-search`,className:`sr-only`,children:`Find a report`}),(0,z.jsx)(o,{id:`report-search`,type:`search`,value:f,onChange:e=>m(e.target.value),placeholder:`Find a report`,className:`h-9 pl-9`})]}),(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[[[`all`,`All`,E.length],[`failed`,`Failed`,D]].map(([e,t,n])=>(0,z.jsxs)(`button`,{type:`button`,"aria-pressed":h===e,onClick:()=>g(e),className:l(`inline-flex min-h-7 cursor-pointer items-center gap-1 rounded-full border px-2.5 text-[12.5px] font-medium`,h===e?`border-accent bg-accent-soft text-ink`:`border-line-soft bg-bg text-muted hover:text-ink`),children:[t,(0,z.jsx)(`span`,{className:l(`tabular-nums`,e===`failed`&&n?`text-fail`:``),children:n})]},e)),N.length>1&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`label`,{htmlFor:`report-kind`,className:`sr-only`,children:`Kind`}),(0,z.jsxs)(c,{id:`report-kind`,value:a,onChange:e=>d(e.target.value),className:`ml-auto h-7 w-auto py-0 pr-7 pl-2.5 text-[12.5px]`,children:[(0,z.jsx)(`option`,{value:``,children:`Every kind`}),N.map(e=>(0,z.jsx)(`option`,{value:e,children:B[e]},e))]})]})]}),(0,z.jsxs)(`ul`,{"aria-label":`Execution reports`,className:`m-0 flex max-h-[42vh] list-none flex-col overflow-y-auto p-0 @2xl:max-h-[calc(100vh-230px)]`,children:[O.length===0&&(0,z.jsx)(`li`,{className:`py-4 text-sm text-muted`,children:t.rows.length?`Nothing matches.`:`No reports yet. Runs, suites and monitor rounds show here once they have run.`}),O.slice(0,v).map((e,t,n)=>{let r=A?.key===e.key,i=P(e.startedAt);return(0,z.jsxs)(`li`,{className:`contents`,children:[(t===0||P(n[t-1].startedAt)!==i)&&(0,z.jsx)(`span`,{className:`sticky top-0 z-[1] bg-bg px-3 pt-3 pb-1 text-[12px] font-semibold text-muted`,children:i}),(0,z.jsxs)(`a`,{href:u(`reports`,encodeURIComponent(e.key)),"aria-current":r?`page`:void 0,className:l(`flex min-h-12 min-w-0 items-center gap-2.5 rounded-[10px] px-3 py-1.5 text-ink no-underline hover:text-ink`,r?`bg-surface-strong`:`hover:bg-surface-muted`),children:[(0,z.jsx)(q,{r:e}),(0,z.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,z.jsx)(`span`,{className:`truncate text-[14px] font-medium`,title:e.title,children:e.title}),(0,z.jsx)(`span`,{className:`truncate text-[12px] text-muted`,children:[B[e.scope],e.scope===`page`||!e.counts.total?``:`${e.counts.passed}/${e.counts.total} passed`].filter(Boolean).join(` · `)})]}),(0,z.jsx)(`span`,{className:`flex-none text-[12px] text-muted tabular-nums`,children:F(e.startedAt)})]})]},e.key)}),O.length>v&&(0,z.jsx)(`li`,{className:`px-3 py-2`,children:(0,z.jsxs)(p,{size:`sm`,onClick:()=>y(v+K),children:[`Show `,Math.min(K,O.length-v),` more`]})}),t.total>t.rows.length&&(0,z.jsxs)(`li`,{className:`px-3 py-3 text-[12px] text-muted`,children:[`The newest `,t.rows.length,` of `,t.total,`.`]})]})]}),A?(0,z.jsx)(Q,{run:A,history:j}):(0,z.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col items-start gap-3 rounded-[18px] border border-line p-6`,children:[(0,z.jsx)(s,{size:24,"aria-hidden":`true`,className:`text-muted`}),(0,z.jsx)(`p`,{className:`m-0 max-w-[60ch] leading-relaxed text-ink-2`,children:`Run something from a chat, and its report shows here.`}),(0,z.jsx)(`a`,{href:u(),className:`text-accent`,children:`New chat`})]})]})]})]})}export{te as Reports};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{$ as e,Et as t,Ft as n,It as r,J as i,Q as a,Vt as o,Y as s,Z as c,_t as l,et as u,fn as d,ln as f,t as p,ut as ee}from"./status-xNQO8J6U.js";import{a as m,n as h,r as g,t as _}from"./markdown-B1Rz6VFK.js";import{O as te,j as ne,k as re,n as v,r as y,t as b}from"./index-DuYynJ55.js";var x={name:`message-circle-question-mark`,size:24,node:[[`path`,{d:`M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719`,key:`1sd12s`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`message-circle-question`]};x.node;var ie=o(x),ae={name:`square-terminal`,size:24,node:[[`path`,{d:`m7 11 2-2-2-2`,key:`1lz0vl`}],[`path`,{d:`M11 13h4`,key:`1p7l4v`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,ry:`2`,key:`1m3agn`}]],aliases:[`terminal-square`]};ae.node;var oe=o(ae),S=d(f(),1),C=e=>e&&typeof e==`object`&&!Array.isArray(e)?e:{},w=e=>typeof e==`string`?e:e==null?``:String(e),se=(e,t=400)=>e.length>t?`${e.slice(0,t-1)}…`:e,T=e=>typeof e==`number`?` in ${Math.round(e/1e3)}s`:``;function E(e,t=400){return se(e.replace(/\s+/g,` `).trim(),t).replace(/([\\`*_[\]<>#|~!])/g,`\\$1`)}function D(e){let t=e.replace(/\s+/g,` `).trim();if(!t)return``;let n=t.includes("`")?"``":"`";return`${n}${n==="``"?` `:``}${t}${n==="``"?` `:``}${n}`}function O(e,t){return/^https?:\/\/[^\s)]+$/i.test(t)?`[${E(e||t,120)}](${t})`:E(e)}var k=e=>[D(w(C(e).id)),E(w(C(e).title),200)].filter(Boolean).join(` `);function A(e){return e.replace(/<!--[\s\S]*?(?:-->|$)/g,``).trim()}function ce(e){return e.replace(/\[((?:\\.|[^\]\\])*)\]\(https?:\/\/[^\s)]+\)/g,`$1`).replace(/\\(.)/g,`$1`).replace(/[*`]/g,``)}var j=(e,t)=>({tone:e,kind:`item`,md:t}),le=(e,t)=>({tone:e,kind:`sub`,md:t});function M(e,t=``){let n=t||(e.agent&&e.agent!==`forgeqe`?`**${E(w(e.agent))}:** `:``);switch(e.kind){case`info`:return j(`info`,`${n}${E(w(e.text))}`);case`start`:return j(`dim`,`${n}→ ${D(w(e.tool))}${e.text&&e.text!==e.tool?` ${E(w(e.text),200)}`:``}`);case`tool`:{let t=C(e.file);return j(e.ok===!1?`warn`:`dim`,`${n}${e.ok===!1?`⚠`:`✓`} ${E(w(e.text)||w(e.tool),240)}${t.path?` (${E(w(t.action))} ${D(w(t.path))})`:``}`)}case`say`:{let t=A(w(e.text));return t?j(`say`,`${n}*${E(t)}*`):null}case`test`:return Number(e.attempt)>0?j(e.ok?`ok`:`fail`,`${n}${e.ok?`✓`:`✗`} **Test, attempt ${E(w(e.attempt))}:** ${E(w(e.text),240)}`):j(e.ok?`ok`:`fail`,`${n}${e.ok?`✓`:`✗`} ${E(w(e.text),240)}`);case`plan`:{let t=Array.isArray(e.items)?e.items.map(C):[],r=t.find(e=>e.status===`in_progress`);return j(`info`,`${n}**Plan:** ${t.filter(e=>e.status===`completed`).length} of ${t.length} done${r?`; now: ${E(w(r.text))}`:``}`)}case`review`:return j(e.approved?`ok`:`warn`,`${n}**Review, attempt ${E(w(e.attempt))}:** ${e.approved?`approved`:`changes asked`}. ${E(w(e.summary),240)}`);case`attempt`:return j(`warn`,`${n}**Attempt ${E(w(e.attempt))} of ${E(w(e.max))}:** ${E(w(e.why),240)}`);case`answer`:return j(`dim`,`${n}Attempt ${E(w(e.attempt))}: ${E(w(e.notes)||`changed ${(Array.isArray(e.changed)?e.changed:[]).map(w).join(`, `)}`,240)}`);case`context`:return e.compacted?j(`info`,`${n}Context compacted: the conversation was summarised to make room.`):null;default:return null}}function ue(e,t=``){switch(e.type){case`log`:return j(e.level===`error`?`fail`:e.level===`warn`?`warn`:`dim`,`${t}${e.level===`warn`||e.level===`error`?`⚠ `:``}${E(w(e.text))}`);case`step`:return j(`dim`,`${t}**Step ${E(w(e.step))}** · ${e.source===`memory`?`from memory`:E(w(e.category))} · ${O(w(e.title)||`untitled`,w(e.url))}`);case`memory`:return j(`info`,`${t}↻ ${E(w(e.text))}`);case`thought`:return le(`think`,`*${E(w(e.text))}*`);case`outcome`:return le(e.ok?`ok`:`fail`,`${e.ok?`✓`:`✗`} ${E(w(e.text),300)}`);case`done`:{let n=C(e.result);return j(n.status===`complete`?`ok`:`fail`,`${t}**${E(w(n.status))}:** ${E(w(n.summary))}`)}case`code`:return M(e,t);default:return null}}function de(e){switch(e.type){case`run-start`:return{tone:`info`,kind:`head`,md:`Browser run: ${E(w(e.goal),200)}${e.url?` · ${O(w(e.url).replace(/^https?:\/\//,``),w(e.url))}`:``}`};case`run-event`:return ue(C(e.event));case`run-done`:{let t=C(e.result),n=!e.error&&(t.outcome===`passed`||!t.outcome&&t.status===`complete`);return j(n?`ok`:`fail`,`${n?`✓`:`✗`} **Run ${n?`passed`:`failed`}**${T(e.ms)}: ${E(w(e.error)||w(t.summary))}${e.runDir?` · ${D(w(e.runDir))}`:``}`)}case`suite-start`:return{tone:`info`,kind:`head`,md:`Suite: ${(Array.isArray(e.cases)?e.cases:[]).length} cases, ${E(w(e.parallel))} at once`};case`suite-event`:{let t=C(e.event);if(t.type===`case-start`)return j(`info`,`**Case ${Number(t.index)+1} of ${E(w(t.total))}:** ${k(t.case)}`);if(t.type===`case-event`)return ue(C(t.event),`${D(w(C(t.case).id))} `);if(t.type===`case-done`){let e=C(t.result);return j(e.status===`passed`?`ok`:`fail`,`${e.status===`passed`?`✓`:`✗`} ${k(e.case)}: **${E(w(e.status))}**${T(e.ms)}${e.summary?`. ${E(w(e.summary),240)}`:``}`)}return t.type===`code-start`?j(`info`,`${D(w(C(t.case).id))} writing its test`):t.type===`writeback`?j(`dim`,`Posted the result back: ${E(JSON.stringify(t.item),240)}`):null}case`suite-done`:{let t=(Array.isArray(C(e.suite).results)?C(e.suite).results:[]).map(C),n=t.filter(e=>e.status===`passed`).length;return j(n===t.length?`ok`:`fail`,`**Suite: ${n} of ${t.length} passed**${T(C(e.suite).ms)}`)}case`info`:return j(e.ok===!1?`fail`:e.ok===!0?`ok`:`info`,E(w(e.text)));case`agent`:return M(C(C(e.event)),`**Coding agent:** `);case`code-start`:return{tone:`info`,kind:`head`,md:`Writing a test: ${E(w(e.goal),200)}`};case`code-done`:return j(e.error?`fail`:`ok`,`${e.error?`✗`:`✓`} **Test ${e.error?`not written`:`written`}**${T(e.ms)}${e.error?`: ${E(w(e.error),240)}`:``}`);case`card`:{let t=C(e.card),n=(Array.isArray(t.body)?t.body:[]).map(w).filter(Boolean);return j(t.status===`ok`?`ok`:t.status===`fail`?`fail`:`info`,`**${E(w(t.title))}**${t.stats?` · ${E(w(t.stats))}`:``}${n.length?`: ${E(n.join(`; `),300)}`:``}`)}case`report`:return j(`ok`,`✓ Report saved: ${E(w(e.title))}`);case`call-start`:return j(`dim`,`→ ${E(w(e.text),240)}`);case`call`:return j(e.ok===!1?`warn`:`dim`,`${e.ok===!1?`⚠`:`✓`} ${E(w(e.text),240)}`);default:return null}}function N(e){let t=w(e.at)||w(e.t),n=null;switch(e.type){case`user`:n=j(`you`,`**You:** ${E(w(e.text),240)}`);break;case`agent`:n=M(C(e.event));break;case`tool`:n=de(C(e.event));break;case`ask`:n=j(`you`,`**Asked:** ${E(w(C(e.question).title))}`);break;case`wait`:n=j(`you`,`**Waiting for you:** ${E(w(e.prompt))}`);break;case`answered`:n=j(`you`,`**You:** ${e.label===void 0?e.ok?`done, continue`:`cancel`:E(w(e.label))}`);break;case`turn_done`:n=j(e.outcome===`done`?`ok`:e.outcome===`stopped`?`warn`:`fail`,`**${e.outcome===`done`?`Done`:e.outcome===`stopped`?`Stopped`:e.outcome===`needs_input`?`Needs your input`:`Failed`}**${e.error?`: ${E(w(e.error),300)}`:``}`);break;case`settings`:n=j(`you`,`**Settings:** browser ${e.headed?`shown`:`headless`}, ${e.writeTests?`passed runs become tests`:`no tests written`}`);break;case`stderr`:n={tone:`dim`,kind:`out`,md:w(e.text)};break;case`error`:n=j(`warn`,`⚠ ${E(w(e.message))}`);break;case`fatal`:n=j(`fail`,`✗ **ForgeQE cannot go on:** ${E(w(e.message))}`);break;case`exit`:n=j(e.code===0?`dim`:`fail`,`ForgeQE stopped${e.code!==null&&e.code!==void 0?` (exit ${E(w(e.code))})`:``}${e.message?`: ${E(w(e.message))}`:``}`)}return n?{at:t,...n,plain:n.kind===`out`?n.md:ce(n.md)}:null}function P(e,t){let n=e?Math.max(0,Math.round((Date.parse(t)-Date.parse(e))/1e3)):0;return Number.isFinite(n)?`+${Math.floor(n/60)}:${String(n%60).padStart(2,`0`)}`:``}function fe(e,t,n){let r=n?[`## ${E(n,200)}`,``]:[],i=[],a=()=>{if(!i.length)return;let e=Math.max(2,...i.map(e=>Math.max(0,...(e.match(/`+/g)||[]).map(e=>e.length)))),t="`".repeat(e+1);r.push(``,`${t}text`,...i,t,``),i=[]};for(let n of e){let e=`\`${P(t,n.at)}\``;n.kind===`out`?i.push(`${P(t,n.at)} ${n.md}`):(a(),n.kind===`head`?r.push(``,`#### ${n.md} ${e}`,``):n.kind===`sub`?r.push(` - ${n.md}`):r.push(`- ${e} ${n.md}`))}return a(),r.join(`
|
|
2
|
-
`).replace(/\n{3,}/g,`
|
|
3
|
-
|
|
4
|
-
`).trim()+`
|
|
5
|
-
`}var F=c();function I({diff:e,className:t}){let n=0,r=0,i=e.split(`
|
|
6
|
-
`).flatMap((e,t)=>{if(/^(diff |index |--- |\+\+\+ )/.test(e))return[];let i=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(e);return i?(n=Number(i[1]),r=Number(i[2]),[{key:t,kind:`hunk`,text:e,a:``,b:``}]):e.startsWith(`+`)?[{key:t,kind:`add`,text:e.slice(1),a:``,b:String(r++)}]:e.startsWith(`-`)?[{key:t,kind:`del`,text:e.slice(1),a:String(n++),b:``}]:e.startsWith(`\\`)?[{key:t,kind:`hunk`,text:e,a:``,b:``}]:[{key:t,kind:`same`,text:e.startsWith(` `)?e.slice(1):e,a:String(n++),b:String(r++)}]});return(0,F.jsx)(`div`,{className:a(`max-h-[420px] overflow-auto rounded-[10px] border border-line-soft bg-bg font-mono text-[12px] leading-[1.6]`,t),children:(0,F.jsx)(`table`,{className:`w-full border-collapse`,children:(0,F.jsx)(`tbody`,{children:i.map(e=>(0,F.jsxs)(`tr`,{className:e.kind===`add`?`bg-pass-soft`:e.kind===`del`?`bg-fail-soft`:e.kind===`hunk`?`bg-surface-muted`:void 0,children:[(0,F.jsx)(`td`,{className:`w-10 px-2 text-right align-top text-muted tabular-nums select-none`,children:e.a}),(0,F.jsx)(`td`,{className:`w-10 px-2 text-right align-top text-muted tabular-nums select-none`,children:e.b}),(0,F.jsx)(`td`,{"aria-hidden":`true`,className:a(`w-4 align-top select-none`,e.kind===`add`?`text-pass`:e.kind===`del`?`text-fail`:`text-muted`),children:e.kind===`add`?`+`:e.kind===`del`?`−`:``}),(0,F.jsxs)(`td`,{className:a(`pr-3 align-top whitespace-pre`,e.kind===`hunk`?`text-muted`:`text-ink`),children:[(0,F.jsx)(`span`,{className:`sr-only`,children:e.kind===`add`?`added: `:e.kind===`del`?`removed: `:``}),e.text||` `]})]},e.key))})})})}var L=e=>{let t=R(e);return typeof t.input==`number`&&typeof t.output==`number`?{input:t.input,output:t.output,cached:typeof t.cached==`number`?t.cached:void 0}:void 0},R=e=>e&&typeof e==`object`&&!Array.isArray(e)?e:{},z=e=>typeof e==`string`?e:e==null?``:String(e),pe=[[/find_test_cases|story_test_cases|check_test_cases|list_sprints/,`Finding test cases`,`searching`],[/environment|logins/,`Preparing the environment`,`handing`],[/run_test_cases|browser_run|suite|run_goal|run_direct/,`Running in the browser`,`browsing`],[/comment_on_pr/,`Commenting on the pull request`,`working`],[/write_back|post_result|post_results|file_bugs|create_bugs/,`Posting the result`,`working`],[/write_test|heal/,`Writing the test`,`writing`],[/run_tests|bash|shell/,`Running the tests`,`working`],[/read_confluence|read|grep|glob|list|webfetch/,`Reading`,`reading`],[/edit|write|patch/,`Changing the code`,`writing`],[/task/,`Handing work to another agent`,`handing`]],me=/run_test_cases|browser_run|run_suite|write_test/,he=[[/find_test_cases|story_test_cases|check_test_cases/,`forgeqe-find`],[/run_test_cases|browser_run|run_goal|run_direct|suite|explore_run/,`engine`],[/write_test/,`forgeqe-test`],[/heal/,`forgeqe-heal`],[/review_pr|pr_review/,`forgeqe-pr-review`],[/api_plan/,`forgeqe-api-plan`],[/write_api|api_test/,`forgeqe-api`],[/explore_plan|plan_charters/,`forgeqe-explore-plan`],[/defect_rca|root_cause/,`forgeqe-defect-rca`],[/insights|forgeqe_bi|defect_intelligence/,`forgeqe-bi`],[/refine/,`forgeqe-refine`]];function B(e){let t=e.toLowerCase();if(!V(t))return he.find(([e])=>e.test(t))?.[1]}var ge=[[/^(azure_devops|ado|azuredevops)_/,`Azure DevOps`],[/^(jira|atlassian)_/,`Jira`],[/^confluence_/,`Confluence`],[/^github_/,`GitHub`],[/^xray_/,`Xray`],[/^testrail_/,`TestRail`],[/^zephyr_/,`Zephyr Scale`],[/^qtest_/,`qTest`]],_e=/(^|_)(create|update|add|delete|remove|post|comment|link|unlink|upload|set|assign|transition|edit|merge|close|reopen|queue|trigger|run|push|move|copy|import|write|publish|approve|vote|lock|unlock)(_|$)/;function V(e){let t=e.toLowerCase();if(!t.startsWith(`forgeqe_`))return ge.find(([e])=>e.test(t))?.[1]}var ve=e=>{let t=R(e);return typeof t.diff==`string`&&t.diff?{diff:t.diff,added:Number(t.added)||0,removed:Number(t.removed)||0}:void 0},H=e=>Array.isArray(e)?e.map(z).filter(Boolean):[];function ye(e,t,n){let r=z(e.status)||(t?`failed`:``);return{status:r,ok:!t&&/^(passed|pass|written|ok|known_defect)$/i.test(r),...z(e.testFile)?{testFile:z(e.testFile)}:{},...z(e.testName)?{testName:z(e.testName)}:{},...z(e.command)?{command:z(e.command)}:{},...typeof e.attempts==`number`?{attempts:e.attempts}:{},...typeof e.maxAttempts==`number`?{maxAttempts:e.maxAttempts}:{},changed:H(e.changed),reused:H(e.reused),...n?{runDir:n}:{},...t?{error:t}:{},...z(e.notes)?{notes:z(e.notes)}:{}}}function be(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){let e=R(n),r=(typeof n==`string`?n:z(e.label)||z(e.request)).replace(/\s+/g,` `).trim(),i=(typeof n==`string`?n:z(e.request)||z(e.label)).trim();r&&i&&!t.some(e=>e.label.toLowerCase()===r.toLowerCase())&&t.push({label:r.length>60?`${r.slice(0,59)}…`:r,request:i})}return t.slice(0,4)}function U(e){let t=e.toLowerCase(),n=V(t);if(n)return _e.test(t.replace(/^[a-z]+_/,``))?{label:`Updating ${n}`,orb:`working`}:{label:`Reading ${n}`,orb:`reading`};for(let[e,n,r]of pe)if(e.test(t))return{label:n,orb:r};let r=t.replace(/^forgeqe_/,``).replace(/[_-]+/g,` `).trim();return{label:r?r[0].toUpperCase()+r.slice(1):`Working`,orb:`working`}}function xe(e,t){return{id:e,user:t,steps:[],parts:[],next:[],asks:[],waits:[],log:[],plan:[],changes:[],tests:[],reports:[]}}function Se(e){let t=R(e);return[z(t.id),z(t.title)].filter(Boolean).join(`: `)}function Ce(e){let t={turns:[],notes:[]},n=new Map,r=e=>(typeof e==`string`?n.get(e):void 0)??t.turns.at(-1),i=(e,t)=>{let n=e=>{for(let r of e){if(r.key===t)return r;let e=r.children&&n(r.children);if(e)return e}};return n(e.steps)},a=(e,t,n)=>{let r={lines:[],...t};if(n)n.push(r);else{let t=e.plan.find(e=>e.status===`active`)??e.plan.find(e=>e.status===`pending`)??e.plan.at(-1);t&&(r.phase=t.text),e.steps.push(r)}return r},o=(e,t,n)=>{let r=t.parent?i(e,`c:${z(t.parent)}`):void 0;if(r)return r.children??=[];let o=z(t.agent);if(!n||!o||o===`forgeqe`)return;let s=[...e.steps].reverse().find(e=>e.status===`running`);return s||=a(e,{key:`ag:${o}:${e.steps.length}`,label:y(o).name,status:`running`,orb:`handing`,agent:o}),s.agent??=o,s.children??=[]},s=(e,n,r)=>{let s=z(n.kind),c=z(n.id);if((s===`start`||s===`tool`)&&me.test(z(n.tool))&&!V(z(n.tool)))return;let l=o(e,n,r),u=R(n.delegate),d=z(u.agent)?{agent:z(u.agent),task:z(u.task)}:void 0;if(s===`start`){if(d)a(e,{key:`c:${c}`,label:`Hands off to ${y(d.agent).name}`,arg:d.task||void 0,status:`running`,orb:`handing`,agent:d.agent,handoff:d,children:[]},l);else{let{label:t,orb:r}=U(z(n.tool)||z(n.text)),i=l?void 0:B(z(n.tool));a(e,{key:`c:${c}`,label:t,arg:z(n.text)&&z(n.text)!==z(n.tool)?z(n.text):void 0,status:`running`,orb:r,...i?{agent:i}:{}},l)}}else if(s===`tool`){let t=c?i(e,`c:${c}`):void 0,r=R(n.file),o=ve(n.change);if(o&&z(r.path)){let t=e.changes.find(e=>e.path===z(r.path));t?Object.assign(t,{diff:`${t.diff}\n${o.diff}`,added:t.added+o.added,removed:t.removed+o.removed}):e.changes.push({path:z(r.path),...o,...z(n.agent)?{agent:z(n.agent)}:{}})}if(t)t.status=n.ok===!1?`fail`:`ok`,t.handoff&&z(u.result)&&(t.handoff.result=z(u.result));else if(d)a(e,{key:`c:${c||e.steps.length}`,label:`Hands off to ${y(d.agent).name}`,arg:d.task||void 0,status:n.ok===!1?`fail`:`ok`,orb:`handing`,agent:d.agent,handoff:{...d,...z(u.result)?{result:z(u.result)}:{}},children:[]},l);else{let{label:t,orb:i}=U(z(n.tool)||z(n.text)),s=l?void 0:B(z(n.tool));a(e,{key:`c:${c||e.steps.length}`,label:t,arg:z(r.path)||z(n.text)||void 0,status:n.ok===!1?`fail`:`ok`,orb:i,...s?{agent:s}:{},...o?{change:o}:{}},l)}t&&o&&(t.change=o)}else if(s===`stream`||s===`say`){if(r)return;let t=e.parts.find(e=>e.id===c);t?t.text=s===`say`?z(n.text):t.text+z(n.text):e.parts.push({id:c||`p${e.parts.length}`,text:z(n.text)})}else if(s===`plan`){if(l||n.agent&&n.agent!==`forgeqe`)return;let t=Array.isArray(n.items)?n.items.map(R):[],r=e=>e===`completed`?`done`:e===`in_progress`?`active`:e===`cancelled`?`skipped`:`pending`;e.plan=t.map(e=>({text:z(e.text),status:r(e.status)})).filter(e=>e.text)}else if(s===`test`){let t=Number(n.attempt)||0;if(t>0)a(e,{key:`t:${e.steps.length}`,label:`Test, attempt ${t}`,arg:z(n.text),status:n.ok?`ok`:`fail`,orb:`retrying`},l);else if(n.ok&&/\bconnected$/i.test(z(n.text)))return;else a(e,{key:`t:${e.steps.length}`,label:z(n.text)||(n.ok?`Checked`:`Check failed`),status:n.ok?`ok`:`fail`,orb:/connect|mcp/i.test(z(n.text))?`waiting`:`working`},l)}else if(s===`review`)a(e,{key:`r:${e.steps.length}`,label:n.approved?`Review approved`:`Review asked for changes`,status:n.approved?`ok`:`info`,orb:`thinking`,agent:`forgeqe-review`,lines:[{text:z(n.summary)}]});else if((s===`context`||s===`usage`)&&!r)s===`context`&&typeof n.tokens==`number`&&typeof n.limit==`number`&&(t.context={tokens:n.tokens,limit:n.limit,compactsAt:typeof n.compactsAt==`number`?n.compactsAt:void 0}),s===`usage`&&(t.usage=L(n.usage)??t.usage);else if(s===`info`){let t=(l??e.steps).at(-1);t&&t.lines.push({text:z(n.text)})}},c,l=(e,t)=>{let n=z(t.type);if(n===`run-start`)a(e,{key:`run:${e.steps.length}`,label:`Running in the browser`,arg:z(t.goal),status:`running`,orb:`browsing`,agent:`engine`});else if(n===`run-event`){let n=[...e.steps].reverse().find(e=>e.key.startsWith(`run:`)),r=R(t.event);if(!n)return;r.type===`outcome`?n.lines.push({text:`Step ${z(r.step)}: ${z(r.action)||z(r.text)}`,ok:r.ok===!0||r.ok!==!1&&void 0}):r.type===`log`&&(r.level!==`info`||r.progress)&&n.lines.push({text:z(r.text),ok:r.level!==`error`&&void 0})}else if(n===`run-done`){let n=[...e.steps].reverse().find(e=>e.key.startsWith(`run:`)&&e.status===`running`),r=R(t.result),i=!t.error&&(r.outcome===`passed`||!r.outcome&&r.status===`complete`);if(n){n.status=i?`ok`:`fail`;let e=z(t.error)||z(r.summary);e&&n.lines.push({text:e,ok:!!i})}z(t.runDir)&&e.reports.push({label:i?`Browser run report`:`Browser run report (failed)`,path:z(t.runDir)})}else if(n===`suite-start`){let n=Array.isArray(t.cases)?t.cases:[];a(e,{key:`suite:${e.steps.length}`,label:`Running ${n.length} test case${n.length===1?``:`s`}`,status:`running`,orb:`working`,agent:`engine`})}else if(n===`suite-event`){let n=[...e.steps].reverse().find(e=>e.key.startsWith(`suite:`)),r=R(t.event);if(n&&r.type===`case-done`){let e=R(r.result);n.lines.push({text:`${Se(e.case)}: ${z(e.status)}`,ok:e.status===`passed`})}}else if(n===`suite-done`){let n=[...e.steps].reverse().find(e=>e.key.startsWith(`suite:`)),r=Array.isArray(R(t.suite).results)?R(t.suite).results.map(R):[];if(n){let e=r.filter(e=>e.status!==`passed`).length;n.status=e?`fail`:`ok`,n.arg=`${r.length-e} of ${r.length} passed`}}else if(n===`card`){let n=R(t.card);a(e,{key:`card:${e.steps.length}`,label:z(n.title),arg:z(n.stats)||void 0,status:n.status===`ok`?`ok`:n.status===`fail`?`fail`:`info`,orb:`working`,lines:(Array.isArray(n.body)?n.body:[]).map(e=>({text:z(e)}))})}else if(n===`call-start`&&!t.quiet)a(e,{key:`call:${z(t.id)}`,label:z(t.text),status:`running`,orb:`working`});else if(n===`call`&&!t.quiet){let n=t.id?i(e,`call:${z(t.id)}`):void 0;n?n.status=t.ok===!1?`fail`:`ok`:a(e,{key:`call:${e.steps.length}`,label:z(t.text),status:t.ok===!1?`fail`:`ok`,orb:`working`})}else if(n===`code-start`)c=z(t.runDir)||void 0,a(e,{key:`code:${e.steps.length}`,label:`Writing the test`,arg:z(t.goal),status:`running`,orb:`writing`,agent:`forgeqe-test`});else if(n===`code-done`){let n=[...e.steps].reverse().find(e=>e.key.startsWith(`code:`)&&e.status===`running`);n&&(n.status=t.error?`fail`:`ok`,t.error&&n.lines.push({text:z(t.error),ok:!1})),e.tests.push(ye(R(t.result),z(t.error),c)),c=void 0}else if(n===`agent`)s(e,R(t.event),!0);else if(n===`info`){let n=e.steps.at(-1);n?n.lines.push({text:z(t.text),ok:t.ok===!0||t.ok!==!1&&void 0}):a(e,{key:`info:${e.steps.length}`,label:z(t.text),status:t.ok===!1?`fail`:`info`,orb:`working`})}else n===`report`&&(a(e,{key:`report:${e.steps.length}`,label:`Report saved`,arg:z(t.title),status:`ok`,orb:`working`}),z(t.html)&&e.reports.push({label:z(t.title)||`Report`,path:z(t.html)}))};for(let r of e){u(r);let e=N(r);e&&(typeof r.id==`string`&&n.get(r.id)||typeof r.turn==`string`&&n.get(r.turn)||t.turns.at(-1))?.log.push(e)}return t;function u(e){switch(e.type){case`user`:{let r=xe(z(e.id),z(e.text));t.turns.push(r),n.set(r.id,r);break}case`ready`:{let n=R(e.profile);n.name&&(t.model={name:z(n.name),provider:z(n.provider)}),t.writeTests=e.writeTests!==!1,t.headed=e.headed===!0;break}case`settings`:typeof e.writeTests==`boolean`&&(t.writeTests=e.writeTests),typeof e.headed==`boolean`&&(t.headed=e.headed);break;case`turn_start`:{let t=r(e.id);t&&(t.started=z(e.t)||z(e.at));break}case`agent`:{let t=r(e.id);t&&s(t,R(e.event),!1);break}case`tool`:{let t=r(e.id);t&&l(t,R(e.event));break}case`ask`:{let t=r(e.turn),n=R(e.question);t?.asks.push({id:z(e.id),title:z(n.title),detail:z(n.detail)||void 0,lines:Array.isArray(n.lines)?n.lines.map(z):[],options:(Array.isArray(n.options)?n.options:[]).map(e=>({id:z(R(e).id),label:z(R(e).label)}))});break}case`wait`:r(e.turn)?.waits.push({id:z(e.id),prompt:z(e.prompt)});break;case`answered`:for(let n of t.turns){let t=n.asks.find(t=>t.id===e.ask);t&&(t.answer=z(e.label));let r=n.waits.find(t=>t.id===e.ask);r&&(r.answer=e.ok===!0)}break;case`turn_done`:{let n=r(e.id);if(!n)break;n.outcome=e.outcome,n.reply=z(e.reply),n.next=be(e.next),n.error=z(e.error)||void 0,n.ended=z(e.t)||z(e.at),t.usage=L(e.usage)??t.usage;let i=e=>{for(let t of e)t.status===`running`&&(t.status=n.outcome===`done`?`ok`:`info`),t.children&&i(t.children)};if(i(n.steps),n.outcome===`done`)for(let e of n.plan)e.status===`active`&&(e.status=`done`);break}case`error`:e.code!==`busy`&&t.notes.push(z(e.message));break;case`fatal`:t.fatal=z(e.message);break;case`exit`:t.ended={code:typeof e.code==`number`?e.code:null,stderr:Array.isArray(e.stderr)?e.stderr.map(z):void 0,message:z(e.message)||void 0}}}}function we(e){let t=e.asks.find(e=>e.answer===void 0),n=e.waits.find(e=>e.answer===void 0);if(t||n)return{text:`Waiting for you…`,orb:`waiting`};let r=[...e.steps].reverse().find(e=>e.status===`running`);return r?{text:`${r.label}…`,orb:r.orb}:e.parts.some(e=>e.text.trim())&&e.steps.length?{text:`Writing a reply…`,orb:`writing`}:{text:`Thinking…`,orb:`thinking`}}function Te(e){if(!e.started||!e.ended)return`Done`;let t=Math.max(1,Math.round((Date.parse(e.ended)-Date.parse(e.started))/1e3)),n=e.outcome===`stopped`?`Stopped after`:`Worked for`;return t<60?`${n} ${t} second${t===1?``:`s`}`:`${n} ${Math.floor(t/60)} min ${t%60} s`}var Ee={running:`active`,ok:`done`,fail:`failed`,info:`note`};function De(e,t){let n=e=>e===`active`&&!t?`done`:e;if(!e.plan.length)return e.steps.map(e=>({key:e.key,label:e.label,status:n(Ee[e.status]),steps:[],step:e}));let r=new Set(e.plan.map(e=>e.text)),i=new Map,a=``;for(let t of e.steps)t.phase&&r.has(t.phase)&&(a=t.phase),i.set(a,[...i.get(a)||[],t]);let o=e=>e.some(e=>e.status===`running`),s=[],c=i.get(``)||[];c.length&&s.push({key:`plan:start`,label:`Getting started`,status:n(o(c)?`active`:`done`),steps:c});let l=e.plan.map((e,n)=>{let r=i.get(e.text)||[],a=e.status===`done`?`done`:e.status===`skipped`?`skipped`:e.status===`active`||o(r)?`active`:`pending`;return{key:`plan:${n}`,label:e.text,status:a===`active`&&!t?`pending`:a,steps:r}});return[...s,...Oe(l)]}function Oe(e){let t=e.findIndex(e=>e.status===`active`);return t<0?e:e.map((e,n)=>e.status===`skipped`||e.status===`failed`||n===t?e:{...e,status:n<t?`done`:`pending`})}var ke={done:`bg-pass/30`,active:`bg-accent/25`,pending:`bg-line`,failed:`bg-fail/30`,skipped:`bg-line`,note:`bg-line`};function W({status:e,orb:t,px:n=20,spin:o=!1}){let s={width:n,height:n};return e===`active`&&o?(0,F.jsx)(`span`,{role:`img`,"aria-label":`At work`,className:`flex flex-none items-center justify-center`,style:s,children:(0,F.jsx)(l,{size:n-2,strokeWidth:2.5,"aria-hidden":`true`,className:`animate-spin text-accent motion-reduce:animate-none`})}):e===`active`?(0,F.jsx)(i,{state:t,px:n,label:`At work`}):e===`done`?(0,F.jsx)(`span`,{role:`img`,"aria-label":`Done`,className:`flex flex-none items-center justify-center rounded-full bg-pass`,style:s,children:(0,F.jsx)(r,{size:n*.6,strokeWidth:3,"aria-hidden":`true`,className:`text-white`})}):e===`failed`?(0,F.jsx)(`span`,{role:`img`,"aria-label":`Failed`,className:`flex flex-none items-center justify-center rounded-full bg-fail`,style:s,children:(0,F.jsx)(u,{size:n*.6,strokeWidth:3,"aria-hidden":`true`,className:`text-white`})}):e===`note`?(0,F.jsx)(`span`,{role:`img`,"aria-label":`Note`,className:`flex flex-none items-center justify-center`,style:s,children:(0,F.jsx)(`span`,{className:`size-1.5 rounded-full bg-line-strong`})}):(0,F.jsx)(`span`,{role:`img`,"aria-label":e===`skipped`?`Skipped`:`To come`,className:a(`box-border block flex-none rounded-full border-2 border-line-strong`,e===`skipped`&&`border-dashed`),style:s})}var Ae=(e,t)=>e.status===`running`?t?`active`:`done`:e.status===`ok`?`done`:e.status===`fail`?`failed`:`note`,je=e=>/[/\\]|\.\w{1,5}$|^\$ /.test(e)&&!/\s{2,}/.test(e);function G({text:e}){return(0,F.jsx)(`span`,{className:a(`min-w-0 max-w-full truncate rounded-md bg-surface-strong px-1.5 py-0.5 text-[12.5px] text-ink-2`,je(e)&&`font-mono text-[12px]`),children:e})}function Me({step:e}){return(0,F.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-1 p-0 text-[13px] leading-relaxed`,children:e.lines.map((e,t)=>(0,F.jsxs)(`li`,{className:a(`flex gap-1.5 [overflow-wrap:anywhere]`,e.ok===!0?`text-pass`:e.ok===!1?`text-fail`:`text-ink-2`),children:[e.ok!==void 0&&(0,F.jsx)(`span`,{"aria-hidden":`true`,children:e.ok?`✓`:`✗`}),(0,F.jsx)(h,{text:e.text,className:`min-w-0 text-[13px] leading-relaxed text-inherit [&_p]:my-0`})]},t))})}function K({agent:e,named:t=!0}){let n=y(e);return(0,F.jsxs)(`span`,{className:`inline-flex flex-none items-center gap-1.5`,title:n.name,children:[(0,F.jsx)(b,{agent:e,px:18,decorative:t}),t&&(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`span`,{className:`font-medium`,style:{color:n.hue},children:n.name}),(0,F.jsx)(`span`,{"aria-hidden":`true`,className:`text-muted`,children:`·`})]})]})}function q({step:e,from:t,live:n}){let r=e.handoff.agent,i=y(r);return(0,F.jsxs)(`span`,{className:`flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-0.5`,children:[(0,F.jsx)(b,{agent:t,px:18}),(0,F.jsxs)(`span`,{role:`img`,"aria-label":`hands off to`,className:a(`handoff-flow flex-none`,n&&`is-live`),style:{color:i.hue},children:[(0,F.jsx)(`span`,{}),(0,F.jsx)(`span`,{}),(0,F.jsx)(`span`,{})]}),(0,F.jsx)(b,{agent:r,px:20,decorative:!0,className:`handoff-in`}),(0,F.jsx)(`span`,{className:`font-medium`,style:{color:i.hue},children:i.name}),e.arg&&(0,F.jsx)(G,{text:e.arg})]})}function J({step:e,working:t,from:r=v}){let i=e.agent||r,o=Y(e),s=Ae(e,t),[c,l]=(0,S.useState)(null),u=c??((!!e.handoff||!!e.agent)&&s===`active`),d=(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(W,{status:s,orb:e.orb,px:16,spin:!0}),e.handoff?(0,F.jsx)(q,{step:e,from:r,live:s===`active`}):(0,F.jsxs)(`span`,{className:`flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-0.5`,children:[(0,F.jsx)(K,{agent:i,named:i!==r}),(0,F.jsx)(`span`,{className:a(`[overflow-wrap:anywhere]`,s===`active`?`text-ink`:`text-ink-2`),children:e.label}),e.arg&&(0,F.jsx)(G,{text:e.arg}),e.change&&(0,F.jsxs)(`span`,{className:`font-mono text-[12px] tabular-nums`,children:[(0,F.jsxs)(`span`,{className:`text-pass`,children:[`+`,e.change.added]}),` `,(0,F.jsxs)(`span`,{className:`text-fail`,children:[`−`,e.change.removed]})]})]}),o&&(0,F.jsx)(n,{size:14,"aria-hidden":`true`,className:a(`mt-0.5 ml-auto flex-none text-muted transition-transform`,u&&`rotate-180`)})]});return(0,F.jsxs)(`li`,{className:`flex flex-col`,children:[o?(0,F.jsx)(`button`,{type:`button`,"aria-expanded":u,onClick:()=>l(!u),className:`flex min-h-8 w-full cursor-pointer items-start gap-2 rounded-lg border-0 bg-transparent px-1.5 py-1.5 text-left text-[13.5px] hover:bg-surface-muted`,children:d}):(0,F.jsx)(`div`,{className:`flex min-h-8 items-start gap-2 px-1.5 py-1.5 text-[13.5px]`,children:d}),u&&o&&(0,F.jsx)(X,{step:e,working:t,from:r,className:`mb-1 ml-[13px]`})]})}var Y=e=>e.lines.length>0||(e.children?.length??0)>0||!!e.handoff?.result||!!e.change;function X({step:e,working:t,from:n,className:r}){let i=e.children||[],o=e.handoff?.agent||e.agent;return(0,F.jsxs)(`div`,{className:a(`chain-in flex flex-col gap-1.5 border-l-2 py-1 pl-3`,r),style:{borderColor:o?`${y(o).hue}66`:`var(--color-line)`},children:[e.lines.length>0&&(0,F.jsx)(Me,{step:e}),e.change&&(0,F.jsx)(I,{diff:e.change.diff}),i.length>0&&(0,F.jsx)(`ul`,{"aria-label":o?`What ${y(o).name} did`:`Steps`,className:`m-0 flex list-none flex-col p-0`,children:i.map(e=>(0,F.jsx)(J,{step:e,working:t,from:o||n},e.key))}),e.handoff?.result&&(0,F.jsxs)(`div`,{className:`flex flex-col gap-0.5 text-[13px]`,children:[(0,F.jsxs)(`span`,{className:`text-muted`,children:[y(e.handoff.agent).name,` answered`]}),(0,F.jsx)(h,{text:e.handoff.result.length>1200?`${e.handoff.result.slice(0,1199)}…`:e.handoff.result,className:`text-[13px] text-ink-2 [&_p]:my-0`})]})]})}function Ne({node:e,last:t,working:r,now:i,orbed:o}){let s=e.step?[]:e.steps,c=e.step,l=s.length>0||!!i||!!c&&Y(c),[u,d]=(0,S.useState)(null),f=u??(e.status===`active`||e.status===`failed`),p=c?.orb??[...s].reverse().find(e=>e.status===`running`)?.orb??i?.orb??`thinking`;return(0,F.jsxs)(`li`,{className:`flex gap-3`,children:[(0,F.jsxs)(`div`,{className:`flex flex-none flex-col items-center`,children:[(0,F.jsx)(`span`,{className:`mt-[3px]`,children:(0,F.jsx)(W,{status:e.status,orb:p,spin:!o})}),!t&&(0,F.jsx)(`span`,{"aria-hidden":`true`,className:a(`mt-1.5 min-h-4 w-0.5 flex-1 rounded-sm`,ke[e.status])})]}),(0,F.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col pb-2`,children:[l?(0,F.jsxs)(`button`,{type:`button`,"aria-expanded":f,onClick:()=>d(!f),className:`flex min-h-7 w-full cursor-pointer items-start gap-1.5 border-0 bg-transparent p-0 text-left`,children:[(0,F.jsx)(Z,{node:e}),(0,F.jsx)(n,{size:14,"aria-hidden":`true`,className:a(`mt-1 flex-none text-muted transition-transform`,f&&`rotate-180`)}),e.status===`active`&&(0,F.jsx)(`span`,{className:`mt-0.5 ml-1 flex-none rounded-full border border-accent-line bg-accent-soft px-2 py-px text-[11.5px] font-medium text-accent`,children:`In progress`})]}):(0,F.jsx)(`div`,{className:`min-h-7`,children:(0,F.jsx)(Z,{node:e})}),f&&l&&(0,F.jsx)(`div`,{className:`chain-in mt-0.5`,children:c?(0,F.jsx)(X,{step:c,working:r,from:`forgeqe`,className:`mt-1`}):(0,F.jsxs)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:[s.map(e=>(0,F.jsx)(J,{step:e,working:r},e.key)),i&&(0,F.jsx)(`li`,{children:(0,F.jsx)(Q,{live:i,className:`px-1.5`})})]})})]})]})}function Z({node:e}){let t=e.status===`active`?`text-ink`:e.status===`pending`||e.status===`skipped`?`text-muted`:e.status===`failed`?`text-fail`:`text-ink-2`,n=e.step;return n?.handoff?(0,F.jsx)(q,{step:n,from:v,live:e.status===`active`}):(0,F.jsxs)(`span`,{className:a(`flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-0.5 text-sm font-medium`,t,e.status===`skipped`&&`line-through`),children:[n&&(0,F.jsx)(K,{agent:n.agent||`forgeqe`,named:!!n.agent&&n.agent!==`forgeqe`}),e.status===`active`?(0,F.jsx)(`span`,{className:`shimmer [overflow-wrap:anywhere]`,children:(0,F.jsx)(`span`,{children:e.label})}):(0,F.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:e.label}),n?.arg&&(0,F.jsx)(G,{text:n.arg})]})}var Pe={info:`text-ink-2`,ok:`text-pass`,fail:`text-fail`,warn:`text-warn`,dim:`text-muted`,say:`text-ink-2`,you:`text-accent`,think:`text-muted italic`};function Fe(e){let[t,n]=(0,S.useState)(()=>Date.now());(0,S.useEffect)(()=>{let e=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(e)},[]);let r=e?Date.parse(e):NaN;if(Number.isNaN(r))return``;let i=Math.max(0,Math.round((t-r)/1e3));return i<2?`just now`:i<60?`${i}s ago`:`${Math.floor(i/60)} min ago`}function Q({live:e,orb:t=!1,className:n}){let r=Fe(e.latest?.at);return(0,F.jsxs)(`div`,{className:a(`flex min-h-8 items-start gap-2 py-1`,n),children:[(0,F.jsx)(`span`,{className:`mt-0.5 flex size-4 flex-none items-center justify-center`,children:t?(0,F.jsx)(i,{state:e.orb,px:20,label:`At work`}):(0,F.jsxs)(`span`,{"aria-hidden":`true`,className:`relative flex size-2`,children:[(0,F.jsx)(`span`,{className:`absolute inline-flex size-full animate-ping rounded-full bg-accent opacity-60 motion-reduce:animate-none`}),(0,F.jsx)(`span`,{className:`relative inline-flex size-2 rounded-full bg-accent`})]})}),(0,F.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-0.5`,children:[(0,F.jsx)(`span`,{className:`shimmer text-[13.5px] font-medium text-muted`,children:(0,F.jsx)(`span`,{"aria-live":`polite`,children:e.text})}),e.latest&&(0,F.jsxs)(`button`,{type:`button`,onClick:e.onLog,title:`Open the activity log`,className:`flex w-full min-w-0 cursor-pointer items-baseline gap-2 border-0 bg-transparent p-0 text-left hover:underline`,children:[(0,F.jsx)(`span`,{className:a(`min-w-0 truncate font-mono text-[12px]`,Pe[e.latest.tone]),children:e.latest.plain}),(0,F.jsxs)(`span`,{className:`flex-none text-[11.5px] whitespace-nowrap text-muted tabular-nums`,children:[r,r&&` · `,e.events,` `,e.events===1?`event`:`events`]})]})]})]})}function Ie({turn:e,working:t,live:n,folded:r=!1}){if(r)return(0,F.jsx)(Q,{live:n,orb:!0});let i=De(e,t),a=e.plan.length>0&&t?i.find(e=>e.status===`active`)??null:null,o=t&&!a?[{key:`now`,label:n.text,status:`active`,steps:[]}]:[],s=[...i,...o],c=[...i].reverse().find(e=>e.status===`active`);return(0,F.jsx)(`ol`,{"aria-label":`What ForgeQE did`,className:`m-0 flex list-none flex-col p-0 pt-1`,children:s.map((e,r)=>e.key===`now`?(0,F.jsx)(`li`,{className:`flex gap-3`,children:(0,F.jsx)(Q,{live:n,orb:!c,className:`-mt-1 min-w-0 flex-1 py-0`})},`now`):(0,F.jsx)(Ne,{node:e,last:r===s.length-1,working:t,now:a===e?n:void 0,orbed:c===e},e.key))})}var Le={passed:`Passed`,failed:`Failed`,stopped:`Stopped`,blocked:`Blocked`};function $({label:e,children:t}){return(0,F.jsxs)(`div`,{className:`grid grid-cols-[110px_minmax(0,1fr)] items-baseline gap-3 py-1.5 text-sm`,children:[(0,F.jsx)(`span`,{className:`text-muted`,children:e}),(0,F.jsx)(`div`,{className:`min-w-0 [overflow-wrap:anywhere]`,children:t})]})}function Re({text:e}){let[t,n]=(0,S.useState)(!1);return(0,F.jsxs)(`div`,{className:`flex items-start gap-2 rounded-[10px] bg-surface-muted px-3 py-2`,children:[(0,F.jsx)(oe,{size:14,"aria-hidden":`true`,className:`mt-0.5 flex-none text-muted`}),(0,F.jsx)(`code`,{className:`min-w-0 flex-1 font-mono text-[12.5px] break-all whitespace-pre-wrap text-ink`,children:e}),(0,F.jsx)(`button`,{type:`button`,"aria-label":t?`Copied`:`Copy the command`,onClick:async()=>{await g(e)&&(n(!0),setTimeout(()=>n(!1),1500))},className:`inline-flex size-7 flex-none cursor-pointer items-center justify-center rounded-md border-0 bg-transparent text-muted hover:bg-surface-strong hover:text-ink`,children:t?(0,F.jsx)(r,{size:14,"aria-hidden":`true`,className:`text-pass`}):(0,F.jsx)(m,{size:14,"aria-hidden":`true`})})]})}function ze({t}){return(0,F.jsxs)(`div`,{className:`flex flex-col`,children:[(0,F.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 pb-1`,children:[(0,F.jsx)(te,{size:16,"aria-hidden":`true`,className:`text-accent`}),(0,F.jsx)(`span`,{className:`font-medium`,children:`Test written`}),(0,F.jsx)(p,{tone:t.ok?`pass`:t.status===`stopped`?`neutral`:`fail`,children:Le[t.status]||t.status||`Not written`}),t.attempts!==void 0&&(0,F.jsx)(`span`,{className:`text-[13px] text-muted`,children:t.maxAttempts?`attempt ${t.attempts} of ${t.maxAttempts}`:e(t.attempts,`attempt`)})]}),t.testFile&&(0,F.jsx)($,{label:`Test file`,children:(0,F.jsx)(_,{path:t.testFile})}),t.testName&&(0,F.jsx)($,{label:`Test`,children:(0,F.jsx)(`code`,{className:`font-mono text-[12.5px]`,children:t.testName})}),t.command&&(0,F.jsx)($,{label:`Run it`,children:(0,F.jsx)(Re,{text:t.command})}),t.runDir&&(0,F.jsx)($,{label:`From the run`,children:(0,F.jsx)(_,{path:t.runDir})}),t.reused.length>0&&(0,F.jsx)($,{label:`Reused`,children:(0,F.jsx)(`span`,{className:`flex flex-wrap gap-x-2 gap-y-1`,children:t.reused.map(e=>(0,F.jsx)(_,{path:e},e))})}),t.error&&(0,F.jsx)(`p`,{className:`m-0 mt-1 rounded-[10px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:t.error})]})}function Be({c:e}){let[t,r]=(0,S.useState)(!1);return(0,F.jsxs)(`li`,{className:`flex flex-col`,children:[(0,F.jsxs)(`div`,{className:`flex min-h-9 items-center gap-2`,children:[(0,F.jsx)(`button`,{type:`button`,"aria-expanded":t,"aria-label":`${t?`Hide`:`Show`} the changes to ${e.path}`,onClick:()=>r(!t),className:`inline-flex size-7 flex-none cursor-pointer items-center justify-center rounded-md border-0 bg-transparent text-muted hover:bg-surface-strong hover:text-ink`,children:(0,F.jsx)(n,{size:15,"aria-hidden":`true`,className:a(`transition-transform`,!t&&`-rotate-90`)})}),(0,F.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:(0,F.jsx)(_,{path:e.path})}),(0,F.jsxs)(`span`,{className:`flex-none font-mono text-[12px] tabular-nums`,children:[(0,F.jsxs)(`span`,{className:`text-pass`,children:[`+`,e.added]}),` `,(0,F.jsxs)(`span`,{className:`text-fail`,children:[`−`,e.removed]})]})]}),t&&(0,F.jsx)(I,{diff:e.diff,className:`chain-in mb-2 ml-9`})]})}function Ve({turn:n}){let r=n.reports.filter((e,t,n)=>n.findIndex(t=>t.path===e.path)===t),i=new Set(n.changes.map(e=>e.path)),a=[...new Set(n.tests.flatMap(e=>e.changed))].filter(e=>!i.has(e)&&![...i].some(t=>t.endsWith(e)||e.endsWith(t)));return!n.tests.length&&!r.length&&!n.changes.length&&!a.length?null:(0,F.jsxs)(`section`,{"aria-label":`Result`,className:`flex flex-col gap-4 rounded-[14px] border border-line-soft px-4 py-3`,children:[n.tests.map((e,t)=>(0,F.jsx)(ze,{t:e},t)),r.length>0&&(0,F.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,F.jsx)(`span`,{className:`text-sm font-medium`,children:`Reports`}),(0,F.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-1 p-0 text-sm`,children:r.map(e=>(0,F.jsxs)(`li`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,F.jsx)(`span`,{className:`text-ink-2`,children:e.label}),(0,F.jsx)(_,{path:e.path})]},e.path))})]}),(n.changes.length>0||a.length>0)&&(0,F.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,F.jsxs)(`span`,{className:`flex items-center gap-1.5 text-sm font-medium`,children:[(0,F.jsx)(t,{size:15,"aria-hidden":`true`,className:`text-muted`}),`Files changed`,(0,F.jsxs)(`span`,{className:`font-normal text-muted`,children:[e(n.changes.length+a.length,`file`),` · `,(0,F.jsxs)(`span`,{className:`text-pass`,children:[`+`,n.changes.reduce((e,t)=>e+t.added,0)]}),` `,(0,F.jsxs)(`span`,{className:`text-fail`,children:[`−`,n.changes.reduce((e,t)=>e+t.removed,0)]})]})]}),(0,F.jsxs)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:[n.changes.map(e=>(0,F.jsx)(Be,{c:e},e.path)),a.map(e=>(0,F.jsx)(`li`,{className:`flex min-h-9 items-center gap-2 pl-9`,children:(0,F.jsx)(_,{path:e})},e))]})]})]})}function He({lines:e,start:t,live:n,name:i}){let a=(0,S.useRef)(null),o=(0,S.useRef)(!0),[s,c]=(0,S.useState)(!1),l=(0,S.useMemo)(()=>fe(e,t),[e,t]);(0,S.useEffect)(()=>{o.current&&a.current&&(a.current.scrollTop=a.current.scrollHeight)},[l]);let u=`inline-flex min-h-8 cursor-pointer items-center gap-1.5 rounded-lg border-0 bg-transparent px-2 text-[12px] font-medium text-muted hover:bg-surface-strong hover:text-ink`;return(0,F.jsxs)(`div`,{className:`overflow-hidden rounded-[12px] border border-line-soft bg-surface-muted`,children:[(0,F.jsxs)(`div`,{className:`flex min-h-9 items-center gap-1 border-b border-line-soft pr-1 pl-3 text-[12px] text-muted`,children:[(0,F.jsxs)(`span`,{className:`flex-1`,children:[`Markdown · `,e.length,` event`,e.length===1?``:`s`,n&&` · live`]}),(0,F.jsxs)(`button`,{type:`button`,"aria-label":s?`Copied`:`Copy the activity log as Markdown`,onClick:async()=>{try{await navigator.clipboard.writeText(l),c(!0),setTimeout(()=>c(!1),1500)}catch{}},className:u,children:[s?(0,F.jsx)(r,{size:14,"aria-hidden":`true`,className:`text-pass`}):(0,F.jsx)(m,{size:14,"aria-hidden":`true`}),s?`Copied`:`Copy`]}),(0,F.jsxs)(`button`,{type:`button`,"aria-label":`Download the activity log as a Markdown file`,onClick:()=>{let e=URL.createObjectURL(new Blob([l],{type:`text/markdown;charset=utf-8`})),t=document.createElement(`a`);t.href=e,t.download=i,t.click(),setTimeout(()=>URL.revokeObjectURL(e),1e3)},className:u,children:[(0,F.jsx)(re,{size:14,"aria-hidden":`true`}),`.md`]})]}),(0,F.jsx)(`div`,{ref:a,role:`log`,"aria-label":`Activity log`,onScroll:e=>{let t=e.currentTarget;o.current=t.scrollTop+t.clientHeight>=t.scrollHeight-24},className:`max-h-[360px] overflow-y-auto px-4 py-2`,children:(0,F.jsx)(h,{text:l,className:`text-[13px] leading-[1.6] [&_code]:text-[12px] [&_h4]:mt-3 [&_h4]:mb-1 [&_li]:my-0.5 [&_pre]:text-[12px] [&_ul]:my-1`})})]})}function Ue({ask:e,live:t,onAnswer:n}){let r=t&&e.answer===void 0;return(0,F.jsxs)(`div`,{className:a(`flex flex-col gap-3 rounded-[14px] border px-4 py-3`,r?`border-accent-line bg-accent-soft`:`border-line-soft`),children:[(0,F.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,F.jsx)(ie,{size:18,"aria-hidden":`true`,className:`mt-0.5 flex-none text-accent`}),(0,F.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[(0,F.jsx)(`span`,{className:`font-medium`,children:e.title}),e.detail&&(0,F.jsx)(`span`,{className:`text-sm text-ink-2`,children:e.detail}),e.lines.map((e,t)=>(0,F.jsx)(`span`,{className:`text-sm text-ink-2 [overflow-wrap:anywhere]`,children:e},t))]})]}),r?(0,F.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[e.options.map(e=>(0,F.jsx)(s,{size:`sm`,onClick:()=>n(e.id),children:e.label},e.id)),(0,F.jsx)(s,{size:`sm`,variant:`ghost`,onClick:()=>n(null),children:`Cancel`})]}):(0,F.jsx)(`span`,{className:`text-sm text-muted`,children:e.answer===void 0?`Not answered`:`You chose: ${e.answer}`})]})}function We({wait:e,live:t,onProceed:n}){let r=t&&e.answer===void 0;return(0,F.jsxs)(`div`,{className:a(`flex flex-col gap-3 rounded-[14px] border px-4 py-3`,r?`border-accent-line bg-accent-soft`:`border-line-soft`),children:[(0,F.jsxs)(`span`,{className:`flex items-start gap-2`,children:[(0,F.jsx)(ne,{size:18,"aria-hidden":`true`,className:`mt-0.5 flex-none text-accent`}),(0,F.jsx)(`span`,{className:`[overflow-wrap:anywhere]`,children:e.prompt})]}),r?(0,F.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,F.jsx)(s,{size:`sm`,variant:`primary`,onClick:()=>n(!0),children:`Done, continue`}),(0,F.jsx)(s,{size:`sm`,onClick:()=>n(!1),children:`Cancel`})]}):(0,F.jsx)(`span`,{className:`text-sm text-muted`,children:e.answer===void 0?`Not done`:e.answer?`You continued`:`You cancelled`})]})}function Ge({turn:e,live:t,onAnswer:r,onProceed:i}){let o=t&&!e.outcome,[s,c]=(0,S.useState)(null),l=s??o,u=we(e),d=o?u.text:Te(e),f=e.parts.map(e=>A(e.text)).filter(Boolean),[p,m]=(0,S.useState)(!1),g=[...e.log].reverse().find(e=>e.tone!==`you`&&e.tone!==`say`);return(0,F.jsxs)(`div`,{className:`flex gap-3`,children:[(0,F.jsx)(`div`,{className:`size-9 flex-none`,"aria-hidden":`true`,children:(0,F.jsx)(b,{agent:`forgeqe`,px:34,className:a(`mt-0.5`,o&&`agent-at-work`)})}),(0,F.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3 pt-1.5`,children:[(e.steps.length>0||o||e.log.length>0)&&(0,F.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,F.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-3 gap-y-1`,children:[(0,F.jsxs)(`button`,{type:`button`,"aria-expanded":l,disabled:!e.steps.length&&!e.plan.length,onClick:()=>c(!l),className:a(`flex cursor-pointer items-center gap-1.5 border-0 bg-transparent p-0 text-sm font-medium text-muted hover:text-ink disabled:cursor-default`,o&&`shimmer`),children:[(0,F.jsx)(`span`,{"aria-live":`polite`,children:d}),(e.steps.length>0||e.plan.length>0)&&(0,F.jsx)(n,{size:16,"aria-hidden":`true`,className:a(`transition-transform`,l&&`rotate-180`)})]}),e.log.length>0&&(0,F.jsxs)(`button`,{type:`button`,"aria-expanded":p,onClick:()=>m(!p),className:`ml-auto inline-flex min-h-8 cursor-pointer items-center gap-1.5 rounded-lg border-0 bg-transparent px-2 text-[13px] font-medium text-muted hover:bg-surface-muted hover:text-ink`,children:[(0,F.jsx)(ee,{size:14,"aria-hidden":`true`}),`Activity log`,(0,F.jsx)(`span`,{className:`tabular-nums`,children:e.log.length})]})]}),(l||o)&&(e.steps.length>0||e.plan.length>0||o)&&(0,F.jsx)(Ie,{turn:e,working:o,folded:!l,live:{...u,latest:g,events:e.log.length,onLog:()=>m(!0)}}),p&&(0,F.jsx)(He,{lines:e.log,start:e.started||e.log[0]?.at,live:o,name:`forgeqe-activity-${e.id}.md`})]}),e.asks.map(e=>(0,F.jsx)(Ue,{ask:e,live:o,onAnswer:t=>r(e.id,t)},e.id)),e.waits.map(e=>(0,F.jsx)(We,{wait:e,live:o,onProceed:t=>i(e.id,t)},e.id)),e.outcome&&e.reply?(0,F.jsx)(h,{text:e.reply}):f.length>0&&(0,F.jsx)(h,{text:f.join(`
|
|
7
|
-
|
|
8
|
-
`)}),(0,F.jsx)(Ve,{turn:e}),e.error&&(0,F.jsx)(`p`,{role:`alert`,className:`m-0 rounded-[12px] bg-fail-soft px-3 py-2 text-sm text-fail [overflow-wrap:anywhere]`,children:e.error}),e.outcome===`stopped`&&!e.reply&&(0,F.jsx)(`p`,{className:`m-0 text-sm text-muted`,children:`Stopped.`})]})]})}export{N as i,Ge as n,Ce as r,He as t};
|