1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7228],{80593:(e,t,o)=>{o.d(t,{cn:()=>a});var s=o(69241),r=o(29573);function a(...e){return(0,r.QP)((0,s.$)(e))}},97228:(e,t,o)=>{o.r(t),o.d(t,{default:()=>W});var s=o(37876),r=o(29719),a=o(14232),i=o(80593);function n({onResize:e,orientation:t="vertical",className:o}){let[r,l]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{if(!r)return;let o=o=>{e("vertical"===t?o.movementX:o.movementY)},s=()=>{l(!1)};return document.addEventListener("mousemove",o),document.addEventListener("mouseup",s),()=>{document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",s)}},[r,e,t]),(0,s.jsx)("div",{onMouseDown:()=>l(!0),className:(0,i.cn)("group relative flex-shrink-0 bg-[var(--color-editor-border)] hover:bg-blue-500/50 transition-colors cursor-col-resize","vertical"===t?"w-[1px] hover:w-[3px]":"h-[1px] hover:h-[3px]",r&&"bg-blue-500",o),children:(0,s.jsx)("div",{className:(0,i.cn)("absolute inset-0","vertical"===t?"w-[5px] -left-[2px]":"h-[5px] -top-[2px]")})})}var l=o(5259),c=o(71024),d=o(41057),u=o(49279),p=o(92390),m=o(79306),f=o(77856);let h=({code:e,language:t="typescript"})=>(c.A.registerLanguage("jsx",d.A),c.A.registerLanguage("typescript",u.A),c.A.registerLanguage("bash",p.A),c.A.registerLanguage("json",m.A),(0,s.jsx)(c.A,{language:t,style:{...f.A,'pre[class*="language-"]':{...f.A['pre[class*="language-"]'],background:"#26262b",border:"none"}},children:e}));function g(e,t){let o=[];if(e.startsWith("### "))o.push((0,s.jsx)("h3",{className:"text-[14px] font-semibold",children:e.slice(4)},t));else if(e.startsWith("## "))o.push((0,s.jsx)("h2",{className:"text-[18px] font-semibold ",children:e.slice(3)},t));else if(e.startsWith("# "))o.push((0,s.jsx)("h1",{className:"text-[24px] font-bold",children:e.slice(2)},t));else if(""===e.trim())o.push((0,s.jsx)("div",{className:"h-2"},t));else{let r=[],a="",i=!1,n=0;for(;n<e.length;)"*"===e[n]&&"*"===e[n+1]?(a&&(r.push(i?(0,s.jsx)("strong",{children:a},`${t}-${n}`):a),a=""),i=!i,n+=2):(a+=e[n],n++);a&&r.push(i?(0,s.jsx)("strong",{children:a},`${t}-end`):a),o.push((0,s.jsx)("p",{className:"leading-relaxed",children:r},t))}return o}var x=o(82196),y=o(50513),b=o(72562),v=o(11821),w=o(54340),k=o(39120),T=o(35675),j=o(68252),C=o(71003);function N({toolCall:e}){return(0,s.jsxs)("div",{className:"flex items-center gap-2 px-3 py-2 border border-[var(--color-editor-border)] rounded-md bg-[var(--color-editor-tab-bg)]",children:["loading"===e.status?(0,s.jsx)(x.A,{className:"w-4 h-4 text-blue-400 animate-spin flex-shrink-0"}):(0,s.jsx)(y.A,{className:"w-4 h-4 text-green-400 flex-shrink-0"}),(0,s.jsxs)("span",{className:"text-sm text-[var(--color-editor-text)]",children:["loading"===e.status?"Calling":"Called"," ",e.name]})]})}let S=[{id:1,title:"Vibe-fix with failure root-cause analysis",description:"Let the agent trace failures back to their root cause, pulling logs, error rates, and historical context",icon:b.A,flowId:"fix-flaky-test"},{id:5,title:"Summarize your last run in-editor",description:"Skip the dashboard. Get instant summaries of your most recent run, including pass/fail counts, slowest specs, and flaky tests â right inside your editor",icon:v.A,flowId:"test-run-summary"},{id:3,title:"Pinpoint and fix slow tests",description:"Surface the slowest specs across your suite, understand whatâs slowing them down, and let the agent recommend optimizations",icon:w.A,flowId:"fix-slow-tests"},{id:4,title:"Uncover and resolve flaky tests",description:"Identify flaky tests across runs, understand their failure patterns, and let AI propose changes to stabilize them.",icon:k.A,flowId:"fix-flaky-tests"},{id:2,title:"Generate custom reports",description:"Ask an agent to prepare tailored reports for your team or stakeholders",icon:T.A,flowId:"report"}];function E({messages:e,inputValue:t,onInputChange:o,onSendMessage:r,currentPrompt:n,isDemoRunning:l,onActionClick:c}){let d=(0,a.useRef)(null),[u,p]=(0,a.useState)(!0);return(0,a.useEffect)(()=>{p(!0)},[n]),(0,a.useEffect)(()=>{u&&d.current&&(d.current.scrollTop=d.current.scrollHeight)},[e,u]),(0,s.jsxs)("div",{className:"bg-[var(--color-editor-sidebar-bg)] border-l border-[var(--color-editor-border)] flex flex-col flex-shrink-0 w-full min-w-0 h-full",children:[(0,s.jsxs)("div",{className:"px-4 py-3 border-b border-[var(--color-editor-border)] flex items-center gap-2",children:[(0,s.jsx)(j.A,{className:"w-4 h-4 text-blue-400"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-[var(--color-editor-text)]",children:"AI Assistant"})]}),n&&(0,s.jsx)("div",{className:"px-4 py-3 border-b border-[var(--color-editor-border)] bg-[var(--color-editor-tab-bg)]",children:(0,s.jsx)("p",{className:"text-sm text-[var(--color-editor-text)]",children:n})}),(0,s.jsx)("div",{className:"flex-1 overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-[#000] [&::-webkit-scrollbar-thumb]:bg-[#26262b] [&::-webkit-scrollbar-thumb]:min-h-16",ref:d,onScroll:()=>{if(d.current){let{scrollTop:e,scrollHeight:t,clientHeight:o}=d.current,s=e+o>=t-5;!s&&u?p(!1):s&&!u&&p(!0)}},children:(0,s.jsx)("div",{className:"p-4 space-y-4",children:e.map((t,o)=>(0,s.jsxs)("div",{className:"space-y-2",children:[t.content&&(0,s.jsxs)("div",{className:(0,i.cn)("text-sm leading-relaxed break-words","user"===t.role?"px-3 py-2 border border-[var(--color-editor-border)] rounded-md bg-[var(--color-editor-tab-bg)] text-[var(--color-editor-text)]":"text-[var(--color-editor-text)]"),children:[function(e){let t=[],o=!1,r="",a=0,i=e.replace(/<code>([\s\S]*?)<\/code>/g,(e,t)=>`__CODE_BLOCK_START__${t}__CODE_BLOCK_END__`).split("\n");for(let e=0;e<i.length;e++){let n=i[e];if(n.includes("__CODE_BLOCK_START__")){let i=n.split("__CODE_BLOCK_START__");
1i[0].trim()&&t.push(...g(i[0],e));let l=n.indexOf("__CODE_BLOCK_END__");if(-1!==l){let o=n.substring(n.indexOf("__CODE_BLOCK_START__")+20,l),r=n.substring(l+18);t.push((0,s.jsx)(h,{code:o,language:"typescript"},`code-${e}`)),r.trim()&&t.push(...g(r,e))}else o=!0,r=n.substring(n.indexOf("__CODE_BLOCK_START__")+20),a=e}else if(o)if(n.includes("__CODE_BLOCK_END__")){let i=n.indexOf("__CODE_BLOCK_END__");r+="\n"+n.substring(0,i),t.push((0,s.jsx)(h,{code:r,language:"typescript"},`code-${a}`));let l=n.substring(i+18);l.trim()&&t.push(...g(l,e)),o=!1,r=""}else r+="\n"+n;else t.push(...g(n,e))}return(0,s.jsx)("div",{className:"space-y-1",children:t})}(t.content),t.isStreaming&&(0,s.jsx)("span",{className:"inline-block w-1.5 h-4 bg-dark-100 animate-pulse"})]}),t.showActions&&o===e.length-1&&(0,s.jsx)("div",{className:"gap-2 flex-wrap flex",children:S.map(e=>(0,s.jsx)("button",{onClick:()=>c(e.flowId),className:"bg-dark-300 rounded-lg border border-dark-100 overflow-hidden w-full lg:w-auto flex gap-4 items-center justify-between p-2 text-left transition-all duration-300 ease-out hover:border-emerald-400 hover:text-emerald-400",children:(0,s.jsxs)("div",{className:"flex gap-2 items-center",children:[e.icon&&(0,s.jsx)(e.icon,{size:20,stroke:1.5}),(0,s.jsx)("span",{className:"text-lg lg:text-base",children:e.title})]})},`${o}-${e.id}`))}),t.toolCalls&&t.toolCalls.length>0&&(0,s.jsx)("div",{className:"space-y-2",children:t.toolCalls.map((e,t)=>(0,s.jsx)(N,{toolCall:e},e.id+t))})]},o))})}),(0,s.jsx)("div",{className:"p-4 border-t border-[var(--color-editor-border)]",children:(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("input",{"data-slot":"input",value:t,onChange:e=>o(e.target.value),onKeyDown:e=>"Enter"===e.key&&r(),placeholder:"Ask AI anything...",disabled:l,className:(0,i.cn)("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive","flex-1 bg-[var(--color-editor-tab-bg)] border-[var(--color-editor-border)] text-[var(--color-editor-text)] placeholder:text-[var(--color-editor-text-muted)] text-sm")}),(0,s.jsx)("button",{onClick:r,disabled:l,className:"bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 px-[10px] rounded-lg",children:(0,s.jsx)(C.A,{className:"w-4 h-4"})})]})})]})}function I({activeTab:e,tabs:t,editorLoaded:o,editorError:r,diffFileName:i,onEditorReady:n,diffEditorContainerRef:l}){let c=(0,a.useRef)(null),d=(0,a.useRef)(null),u=(0,a.useRef)(null),p=(0,a.useRef)(null),m=(0,a.useRef)(null);return(0,a.useEffect)(()=>{let e=!0,o=o=>{e&&d.current&&!c.current&&(console.log("[v0] Initializing Monaco editor"),p.current=o,o.editor.defineTheme("vs-dark-custom",{base:"vs-dark",inherit:!0,rules:[{token:"comment",foreground:"6A9955"},{token:"keyword",foreground:"C586C0"},{token:"string",foreground:"CE9178"},{token:"number",foreground:"B5CEA8"},{token:"type",foreground:"4EC9B0"},{token:"function",foreground:"DCDCAA"}],colors:{"editor.background":"#1e1e1e","editor.foreground":"#d4d4d4","editorLineNumber.foreground":"#858585","editor.selectionBackground":"#264f78","editor.inactiveSelectionBackground":"#3a3d41"}}),c.current=o.editor.create(d.current,{value:t[0]?.content||"// Select a file from the file tree to start editing",language:"typescript",theme:"vs-dark-custom",fontSize:14,fontFamily:"var(--font-geist-mono), monospace",minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,tabSize:2,lineNumbers:"on",renderWhitespace:"selection",lineNumbersMinChars:2,overviewRulerLanes:0,hideCursorInOverviewRuler:!0,renderOverviewRuler:!1,wordWrap:"on",readOnly:!0}),n(c.current,o),console.log("[v0] Monaco editor created successfully"))};return(()=>{try{if(console.log("[v0] Starting Monaco Editor load"),window.monaco){console.log("[v0] Monaco already loaded, initializing editor"),o(window.monaco);return}if(document.querySelector('script[src*="monaco-editor"]')){console.log("[v0] Monaco script exists, waiting for load");let t=setInterval(()=>{window.monaco&&(clearInterval(t),console.log("[v0] Monaco loaded, initializing editor"),o(window.monaco))},100);setTimeout(()=>{clearInterval(t),!c.current&&e&&console.error("[v0] Monaco load timeout")},5e3);return}let t=document.createElement("script");t.src="https://cdn.jsdelivr.net/npm/[email protected]/min/vs/loader.js",t.async=!0,t.onerror=e=>{console.error("[v0] Failed to load Monaco Editor script:",e)},t.onload=()=>{try{if(console.log("[v0] Monaco script loaded, configuring"),!window.require)return void console.error("[v0] window.require is not available");window.require.config({paths:{vs:"https://cdn.jsdelivr.net/npm/[email protected]/min/vs"}}),window.require(["vs/editor/editor.main"],t=>{e&&(console.log("[v0] Monaco editor main loaded"),o(t))},e=>{console.error("[v0] Error loading Monaco editor main:",e)})}catch(e){console.error("[v0] Error in Monaco initialization:",e)}},document.head.appendChild(t)}catch(e){console.error("[v0] Error setting up Monaco script:",e)}})(),()=>{if(e=!1,c.current)try{c.current.dispose(),c.current=null}catch(e){console.error("[v0] Error disposing editor:",e)}if(m.current)try{m.current.dispose(),m.current=null}catch(e){console.error("[v0] Error disposing diff editor:",e)}}},[]),(0,a.useEffect)(()=>
1{if(console.log("[v0] Active tab changed:",e,"Editor loaded:",o,"Editor exists:",!!c.current),"cases"===e)return void console.log("[v0] Skipping editor update - showing cases panel",i);if(i&&e===i)return void console.log("[v0] Skipping editor update - showing diff for",i);if(c.current&&e&&o){let o=t.find(t=>t.name===e);if(o){console.log("[v0] Updating editor content for:",o.name),c.current.setValue(o.content);let e=o.name.split(".").pop(),t="typescript";if("json"===e?t="json":"tsx"===e?t="typescript":"ts"===e&&(t="typescript"),p.current){let e=c.current.getModel();e&&(p.current.languages.typescript.typescriptDefaults.setCompilerOptions({jsx:"react"}),p.current.languages.typescript.typescriptDefaults.setDiagnosticsOptions({noSemanticValidation:!1,noSyntaxValidation:!1}),p.current.editor.setModelLanguage(e,t))}}}},[e,t,o,i]),(0,s.jsxs)("div",{className:"flex-1 w-full relative",children:[(0,s.jsx)("div",{ref:d,className:"absolute inset-0",style:{display:i&&e===i?"none":"block"}}),(0,s.jsx)("div",{ref:l||u,className:"absolute inset-0",style:{display:i&&e===i?"block":"none"}}),!o&&!r&&(0,s.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-[var(--color-editor-bg)]",children:(0,s.jsxs)("div",{className:"flex items-center gap-2 text-[var(--color-editor-text-muted)]",children:[(0,s.jsx)(x.A,{className:"w-4 h-4 animate-spin"}),(0,s.jsx)("span",{className:"text-sm",children:"Loading editor..."})]})}),r&&(0,s.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-[var(--color-editor-bg)]",children:(0,s.jsxs)("div",{className:"text-center",children:[(0,s.jsx)("p",{className:"text-sm text-red-400 mb-2",children:r}),(0,s.jsx)("p",{className:"text-xs text-[var(--color-editor-text-muted)]",children:"The code editor failed to load. Please refresh the page."})]})})]})}let R=[{type:"text",content:"Would you like a demonstration for another use case?"},{type:"askUser"}],F=[{id:"use-cases",prompt:"What can I do with Currents MCP 2.0?",steps:[{type:"text",content:"I can help you in many ways, choose an option for me to demonstrate:"},{type:"askUser"}]},{id:"fix-flaky-test",prompt:"Fix this flaky test",steps:[{type:"text",content:"I'll help you fix the flaky test. Let me first check the test results to understand what's causing the flakiness.",delay:25},{type:"tool",toolName:"currents-get-test-results",toolId:"tool-1",delay:1500},{type:"text",content:"I can see from the test results that the SearchBar test is flaky because the network mock is registered too late. Sometimes the request fires before the route is set up, so the test misses the mock and fails intermittently. Let me open the test file and make the necessary adjustments.",delay:25},{type:"openFile",fileName:"search-bar.spec.ts",delay:800},{type:"text",content:"I'm going to update the test so that the mock is registered before any requests are triggered, and ensure we wait for the specific search result instead of just counting list items.",delay:25},{type:"editFile",fileName:"search-bar.spec.ts",showDiff:!0,newContent:`test("should show results when searching", async ({ page }) => { 2 // â Mock early, before triggering the request 3 await page.route("**/api/search**", route => 4 route.fulfill({ 5 status: 200, 6 body: JSON.stringify([{ id: 1, text: "result A" }]), 7 }) 8 ); 9 10 await page.goto("http://localhost:3000"); 11 await page.getByPlaceholder("Search...").type("result", { delay: 200 }); 12 13 // â Specifically wait for "apple" result, not just any result 14 await expect(page.locator("li")).toContainText("result A"); 15});`},{type:"text",content:`I've updated the flaky test with the following improvements: 16 17## Changes Made: 18⢠Registered the network mock **before navigation and input** 19⢠Simulated realistic typing with a delay to trigger multiple requests safely 20⢠Updated the assertion to check for the actual result text ("result A") instead of just the count 21 22## Why This Fixes Flakiness: 23⢠**Early mock registration:** Ensures the search request is always intercepted and fulfilled consistently 24⢠**Specific assertion:** Waiting for "result A" avoids false positives when multiple results or empty states exist 25⢠**Typing delay:** Matches real-world user interaction and prevents race conditions 26 27â The test should now be stable and consistently pass!`,delay:40},...R]},{id:"test-run-summary",prompt:"Summarize my last test run",steps:[{type:"text",content:"I'll help you get a summary of your last test run from Currents.",delay:25},{type:"tool",toolName:"currents-get-run-details",toolId:"tool-1",delay:500}
27,{type:"text",content:`# ð Your Last Currents Run Summary 28## Run Overview 29⢠**Run ID:** e0f00a9ac7b17c19 30⢠**Status:** â FAILED 31⢠**Duration:** 1 minute 15 seconds (75.5 seconds) 32⢠**Date:** October 2, 2025 at 12:10 PM UTC 33⢠**Branch:** chore/cicd-optimization 34⢠**Commit:** "chore: update CI/CD pipeline for faster builds" 35## Test Results Summary 36⢠**Total Tests:** 25 37⢠â **Passed:** 23 (92%) 38⢠â **Failed:** 2 (8%) 39⢠ð **Flaky:** 2 40⢠â¸ï¸ **Skipped:** 0 41⢠Ⳡ**Pending:** 0 42 43## Spec File Breakdown 44### 1. onboarding.spec.ts â 45⢠**Status:** 1 failure, 5 passes 46⢠**Duration:** 29.6 seconds 47⢠**Flaky Tests:** 0 48⢠**Tags:** actions, web-app 49### 2. payments.spec.ts â 50⢠**Status:** All 9 tests passed 51⢠**Duration:** 13.6 seconds 52⢠**Flaky Tests:** 0 53⢠**Tags:** annotations, web-app 54### 3. reports.spec.ts â ï¸ 55⢠**Status:** 1 failure, 9 passes, 2 flaky 56⢠**Duration:** 32.0 seconds 57⢠**Flaky Tests:** 2 58⢠**Tags:** attachments, annotations, web-app 59 60## Key Issues Identified 61### Flaky Tests (2 total) 62The reports.spec.ts file contains 2 flaky tests that are causing instability in your test suite. 63### Failed Tests (2 total) 64⢠1 failure in onboarding.spec.ts 65⢠1 failure in reports.spec.ts 66 67## Infrastructure Details 68⢠**Platform:** Ubuntu 22.04 (Linux) 69⢠**Framework:** Playwright 1.50.1 70⢠**Client Version:** 1.9.4 71⢠**Parallel Workers:** 5 workers 72⢠**Coverage:** Disabled 73 74## Recommendations 751. Focus on reports.spec.ts - This file has both failures and flakiness issues 762. Investigate onboarding.spec.ts - Has 1 failure that needs attention 773. Implement flaky test fixes - The 2 flaky tests in reports.spec.ts are likely the ones we identified earlier 784. Consider Currents Test Orchestrator - You're using 5 workers which is good for performance`,delay:15},...R]},{id:"fix-slow-tests",prompt:"Can you help me fix my slowest test?",steps:[{type:"text",content:"I'll help you identify and fix your slowest test. Let me first find the slowest test in your Currents project."},{type:"tool",toolName:"currents-get-test-performance",toolId:"tool-1",delay:250},{type:"text",content:"Now let me get more details about the slowest test to understand what's causing the performance issue."},{type:"tool",toolName:"currents-get-test-results",toolId:"tool-2",delay:250},{type:"text",content:`# ð Your Slowest Test Analysis 79## The Problem Test 80⢠**Test Name:** "Photos Page @coverage > should handle counter interactions" 81⢠**Spec File:** nextjs/pages/photos.spec.ts 82⢠**Average Duration:** 135.15 seconds (2 minutes 15 seconds) 83⢠**Failure Rate:** 88.2% (30 failures out of 34 executions) 84 85## Root Cause Analysis 86### Primary Issue: Test Timeout 87⢠**Timeout Setting:** 30 seconds per attempt 88⢠**Retry Pattern:** 4 attempts per test run 89⢠**Total Time:** ~150 seconds (4 \xd7 30s + retry delays) 90⢠**Error:** Test timeout of 30000ms exceeded 91 92### Why It's Timing Out 93The test is consistently hitting the 30-second timeout on every attempt, suggesting: 941. Infinite Loop or Blocking Operation 952. Missing Wait Conditions 963. Heavy Resource Operations 974. Network/API Dependencies 98 99## Performance Fix Plan 100### Phase 1: Immediate Timeout Fix 101**1.1 Increase Timeout (Temporary)** 102<code>// In your test configuration 103test.setTimeout(60000); // Increase to 60 seconds 104 105// Or for specific test 106test('should handle counter interactions', async ({ page }) => { 107 test.setTimeout(120000); // 2 minutes for this specific test 108 // ... test code 109});</code> 110 111### Phase 2: Identify the Bottleneck 112<code>test('should handle counter interactions', async ({ page }) => { 113 // Wait for page to be fully loaded 114 await page.waitForLoadState('networkidle'); 115 116 // Wait for specific elements to be ready 117 await page.waitForSelector('[data-testid="counter"]', { timeout: 10000 }); 118 119 // Wait for any async operations to complete 120 await page.waitForFunction(() => { 121 return document.querySelector('[data-testid="counter"]')?.textContent !== 'Loading...'; 122 }); 123 124 // Your test logic here 125});</code> 126 127 128### Phase 3: Optimize the Test 129### 3.1 Mock Heavy Dependencies 130<code>// Mock API calls that might be slow 131await page.route('**/api/photos/**', route => { 132 route.fulfill({ 133 status: 200, 134 contentType: 'application/json', 135 body: JSON.stringify({ photos: [] }) 136 }); 137});</code> 138 139### 3.2 Use Specific Selectors 140<code>// Instead of waiting for generic elements 141await page.waitForSelector('[data-testid="counter"]'); 142 143// Wait for specific state 144await page.waitForFunction(() => { 145 const counter = document.querySelector('[data-testid="counter"]'); 146 return counter && counter.textContent !== 'Loading...'; 147});</code> 148 149## Expected Results 150After implementing these fixes: 151⢠**Test Duration:** Reduce from 135s to under 10s 152⢠**Success Rate:** Increase from 11.8% to 95%+ 153⢠**Reliability:** Eliminate timeout issues
154⢠**Maintainability:** Easier to debug and modify 155 156## Next Steps 1571. Start with Phase 1 - Increase timeout and add proper waits 1582. Add logging - Identify exactly where the test is hanging 1593. Optimize step by step - Fix each bottleneck as you find it 1604. Split the test - Break it into smaller, focused tests 161 162Would you like me to help you implement any of these specific fixes, or would you like me to dive deeper into any particular aspect of the optimization? 163`},...R]},{id:"fix-flaky-tests",prompt:"What are my top flaky tests, and how to fix them?",steps:[{type:"text",content:"I'll help you identify your top flaky tests and create a plan to fix them. Let me start by getting your projects and then analyzing the test performance data."},{type:"tool",toolName:"currents-get-projects",toolId:"tool-1",delay:250},{type:"text",content:"I can see you have two projects. Let me get the flaky tests from both projects to identify the most problematic ones."},{type:"tool",toolName:"currents-get-tests-performance",toolId:"tool-2",delay:250},{type:"tool",toolName:"currents-get-tests-performance",toolId:"tool-3",delay:250},{type:"text",content:"Perfect! I found your top flaky tests. Now let me get more detailed information about these tests to understand their failure patterns and create a comprehensive fix plan."},{type:"tool",toolName:"currents-get-test-results",toolId:"tool-4",delay:250},{type:"text",content:"Perfect! I've analyzed your test data and found the patterns. Let me create a comprehensive fix plan for your top flaky tests."},{type:"text",content:`## Your Top Flaky Tests 164Based on the data from your "Demo Project", here are your most problematic flaky tests: 165 166### 1. "should export reports in various formats (PDF, CSV, Excel)" 167⢠**Flakiness Rate:** 11.6% (21 flaky executions out of 181 total) 168⢠**Location:** web-app/reports.spec.ts:118 169⢠**Error Pattern:** expect(received).toBeTruthy() - Received: false 170 171### 2. "should allow collaboration and sharing of reports" 172⢠**Flakiness Rate:** 10.5% (19 flaky executions out of 181 total) 173⢠**Location:** web-app/reports.spec.ts:261 174⢠**Error Pattern:** expect(received).toBeTruthy() - Received: false 175 176### 3. "should allow filtering of reports by date range" 177⢠**Flakiness Rate:** 8.8% (16 flaky executions out of 181 total) 178⢠**Location:** web-app/reports.spec.ts:99 179⢠**Error Pattern:** expect(received).toBeTruthy() - Received: false 180 181## Root Cause Analysis 182All three tests share the same failure pattern: 183⢠They're all in the same spec file (web-app/reports.spec.ts) 184⢠They all fail with expect(received).toBeTruthy() receiving false 185⢠They all retry successfully on the second attempt 186⢠The failures occur at different line numbers (99, 118, 261) suggesting different assertions 187⢠All tests are related to report functionality`},{type:"text",content:`Looking at the test failure logs I analyzed, I can pinpoint the exact source code causing the flakiness for each test. Let me break down the specific issues: 188### 1. "should export reports in various formats (PDF, CSV, Excel)" 189⢠**Location:** web-app/reports.spec.ts:118:43 190⢠**Root Cause:** The test is failing at line 118, column 43 with expect(received).toBeTruthy() receiving false. This suggests: 191<code>// Line 118 in reports.spec.ts - LIKELY CAUSE: 192expect(someElement.isVisible() || someCondition).toBeTruthy(); 193// or 194expect(await page.locator('[data-testid="export-ready"]').isVisible()).toBeTruthy(); 195</code> 196 197**The Problem:** The test is checking if an export element is ready/visible, but there's a race condition where: 198⢠The export button is clicked 199⢠The test immediately checks if the export dialog/status is ready 200⢠But the export process hasn't completed yet, so the condition returns false 201⢠On retry, the export has had time to complete, so it passes 202 203**The Problem:** The test is checking if an export element is ready/visible, but there's a race condition where: 204⢠The export button is clicked 205⢠The test immediately checks if the export dialog/status is ready 206⢠But the export process hasn't completed yet, so the condition returns false 207⢠On retry, the export has had time to complete, so it passes 208 209### 2. "should allow collaboration and sharing of reports" 210⢠**Location:** web-app/reports.spec.ts:261:43 211⢠**Root Cause:** Similar pattern at line 261, column 43: 212<code>// Line 261 in reports.spec.ts - LIKELY CAUSE: 213expect(collaborationPanel.isEnabled() || sharingOption.isVisible()).toBeTruthy(); 214// or 215expect(await page.locator('[data-testid="collaboration-ready"]').isVisible()).toBeTruthy(); 216</code> 217 218**The Problem:** The collaboration/sharing feature has async initialization: 219⢠User clicks to enable collaboration 220⢠Test immediately checks if collaboration panel is ready 221⢠The panel hasn't finished loading/permissions haven't been set up 222⢠On retry, the async operation has completed 223 224### 3. "should allow filtering of reports by date range" 225⢠**Location:** web-app/reports.spec.ts:99:45 226⢠**Root Cause:** Line 99, column 45 with the same pattern: 227<code>// Line 99 in reports.spec.ts - LIKELY CAUSE: 228expect(dateFilter.isEnabled() || filterResults.isVisible()).toBeTruthy(); 229// or 230expect(await page.locator('[data-testid="date-filter-ready"]').isVisible()).toBeTruthy(); 231</code> 232 233**The Problem:** Date filtering involves: 234⢠Setting date range inputs 235⢠Triggering a search/filter operation 236⢠Immediately checking if results are ready 237⢠The filter operation is still processing when the assertion runs 238 239## Common Pattern Analysis 240All three tests share the same fundamental issue: 241 242### The Flaky Code Pattern: 243<code>// This is what's causing the flakiness: 244await page.click('[data-testid="action-button"]'); 245expect(await page.locator('[data-testid="result-element"]').isVisible()).toBeTruthy(); 246</code> 247 248### Why It's Flaky: 249⢠No wait for async operations - The tests don't wait for the triggered action to complete 250⢠Immediate assertion - They check the result before the operation finishes 251⢠Race condition - The timing between action and result is unpredictable 252⢠Retry success - On retry, the operation has had time to complete 253 254## Specific Fixes for Each Test 255### Test 1 - Export Reports (Line 118): 256<code>// BEFORE (Flaky): 257await page.click('[data-testid="export-button"]'); 258expect(await page.locator('[data-testid="export-ready"]').isVisible()).toBeTruthy(); 259 260// AFTER (Stable): 261await page.click('[data-testid="export-button"]'); 262await page.waitForSelector('[data-testid="export-ready"]', { timeout: 10000 }); 263expect(await page.locator('[data-testid="export-ready"]').isVisible()).toBeTruthy(); 264</code> 265 266### Test 2 - Collaboration (Line 261): 267<code>// BEFORE (Flaky): 268await page.click('[data-testid="enable-collaboration"]'); 269expect(await page.locator('[data-testid="collaboration-ready"]').isVisible()).toBeTruthy(); 270 271// AFTER (Stable): 272await page.click('[data-testid="enable-collaboration"]'); 273await page.waitForSelector('[data-testid="collaboration-ready"]', { timeout: 10000 }); 274expect(await page.locator('[data-testid="collaboration-ready"]').isVisible()).toBeTruthy(); 275</code> 276 277### Test 3 - Date Filtering (Line 99): 278<code>// BEFORE (Flaky): 279await page.fill('[data-testid="start-date"]', '2024-01-01'); 280await page.fill('[data-testid="end-date"]', '2024-12-31'); 281await page.click('[data-testid="apply-filter"]'); 282expect(await page.locator('[data-testid="filter-results"]').isVisible()).toBeTruthy(); 283 284// AFTER (Stable): 285await page.fill('[data-testid="start-date"]', '2024-01-01'); 286await page.fill('[data-testid="end-date"]', '2024-12-31'); 287await page.click('[data-testid="apply-filter"]'); 288await page.waitForSelector('[data-testid="filter-results"]', { timeout: 10000 }); 289expect(await page.locator('[data-testid="filter-results"]').isVisible()).toBeTruthy(); 290</code> 291 292## The Core Issue 293The flakiness is caused by missing wait strategies for async operations. The tests are checking for results before the operations complete, creating a race condition that sometimes passes (when the operation is fast) and sometimes fails (when the operation takes longer). 294The fix is to add proper waitForSelector calls before the assertions to ensure the async operations have completed before checking their results.`},...R]},{id:"report",prompt:"Please tell me the % of failure runs in the last month.",steps:[{type:"text",content:"I'll help you with a report of the failure rate in the last month."},{type:"tool",toolName:"currents-get-test-performance",toolId:"tool-1",delay:250}
294,{type:"text",content:`# ð Failure Rate Analysis - Last Month 295## Overall Failure Statistics 296 297### By Spec File: 2981. docs/docs.spec.ts 299⢠**Total Executions:** 93 300⢠**Failed Executions:** 0 301⢠**Failure Rate:** 0% â 302 3032. web-app/onboarding.spec.ts 304⢠**Total Executions:** 188 305⢠**Failed Executions:** 0 306⢠**Failure Rate:** 0% â 307 3083. web-app/reports.spec.ts 309⢠**Total Executions:** 187 310⢠**Failed Executions:** 187 311⢠**Failure Rate:** 100% â 312 3134.landing-page/landing-page.spec.ts 314⢠**Total Executions:** 94 315⢠**Failed Executions:** 94 316⢠**Failure Rate:** 100% â 317 3185. web-app/payments.spec.ts 319⢠**Total Executions:** 186 320⢠**Failed Executions:** 186 321⢠**Failure Rate:** 100% â 322 323## Overall Project Failure Rate 324⢠**Total Executions:** 748 runs 325⢠**Total Failed Executions:** 467 runs 326⢠**Overall Failure Rate:** 62.4% â 327 328## Key Insights 329### Critical Issues: 330⢠3 out of 5 spec files have 100% failure rate 331⢠Only 2 spec files are passing consistently 332⢠reports.spec.ts and payments.spec.ts are completely broken 333 334### Flaky Test Issues: 335⢠**reports.spec.ts:** 65.2% flaky rate (122 flaky executions) 336⢠**onboarding.spec.ts:** 14.4% flaky rate (27 flaky executions) 337⢠**payments.spec.ts:** 29.6% flaky rate (55 flaky executions) 338 339## Immediate Action Required 340⢠Fix the 100% failure rate specs - These are completely broken 341⢠Address flaky tests - High flakiness is masking real issues 342⢠Investigate root causes - The failure patterns suggest systematic issues 343 344## Recommendations 345⢠**Priority 1**: Fix reports.spec.ts, landing-page.spec.ts, and payments.spec.ts 346⢠**Priority 2**: Reduce flakiness in all specs 347⢠**Priority 3**: Implement better test stability measures 348 349The 62.4% failure rate indicates significant test suite instability that needs immediate attention.`,delay:25},...R]}],A=[{name:"src",type:"folder",children:[{name:"search-bar.tsx",type:"file",content:`import React, { useState } from "react"; 350 351interface Result { 352 id: number; 353 text: string; 354} 355 356export const SearchBar: React.FC = () => { 357 const [query, setQuery] = useState(""); 358 const [results, setResults] = useState<Result[]>([]); 359 const [loading, setLoading] = useState(false); 360 361 const handleSearch = (value: string) => { 362 setQuery(value); 363 if (!value) { 364 setResults([]); 365 return; 366 } 367 368 setLoading(true); 369 // Simulate network delay between 200ms - 1200ms 370 const delay = 200 + Math.random() * 1000; 371 372 setTimeout(() => { 373 setResults([ 374 { id: 1, text: \`\${value} result A\` }, 375 { id: 2, text: \`\${value} result B\` }, 376 ]); 377 setLoading(false); 378 }, delay); 379 }; 380 381 return ( 382 <div> 383 <input 384 type="text" 385 placeholder="Search..." 386 value={query} 387 onChange={(e) => handleSearch(e.target.value)} 388 /> 389 {loading && <div role="status">Loading...</div>} 390 <ul> 391 {results.map((r) => ( 392 <li key={r.id}>{r.text}</li> 393 ))} 394 </ul> 395 </div> 396 ); 397}; 398`}]},{name:"tests",type:"folder",children:[{name:"search-bar.spec.ts",type:"file",content:`import { test, expect } from "@playwright/test"; 399 400test("should show results when searching", async ({ page }) => { 401 await page.goto("http://localhost:3000"); 402 403 await page.getByPlaceholder("Search...").fill("result"); 404 405 await page.route("**/api/search**", route => 406 route.fulfill({ 407 status: 200, 408 body: JSON.stringify([{ id: 1, text: "result A" }]), 409 }) 410 ); 411 412 await expect(page.locator("li")).toHaveCount(1); 413}); 414`}]},{name:"playwright.config.ts",type:"file",content:`import { CurrentsConfig, currentsReporter } from "@currents/playwright"; 415import { defineConfig, devices } from "@playwright/test"; 416 417import dotenv from "dotenv"; 418dotenv.config(); 419 420const currentsConfig: CurrentsConfig = { 421 recordKey: process.env.CURRENTS_RECORD_KEY!, 422 projectId: process.env.CURRENTS_PROJECT_ID!, 423 coverage: { 424 projects: true, 425 }, 426}; 427 428/** 429 * See https://playwright.dev/docs/test-configuration. 430 */ 431export default defineConfig({ 432 testDir: "./tests", 433 retries: 3, 434 use: { 435 baseURL: "https://currents.dev", 436 trace: "on", 437 video: "on", 438 screenshot: "on", 439 }, 440 reporter: [currentsReporter(currentsConfig)], 441 projects: [ 442 {
443 name: "web-app", 444 use: { ...devices["Desktop Chrome"] }, 445 testDir: "./tests/web-app", 446 }, 447 { 448 name: "docs", 449 use: { ...devices["Desktop Chrome"] }, 450 testDir: "./tests/docs", 451 }, 452 { 453 name: "landing-page", 454 use: { ...devices["Desktop Chrome"] }, 455 testDir: "./tests/landing-page", 456 }, 457 { 458 name: "nextjs", 459 use: { ...devices["Desktop Chrome"] }, 460 testDir: "./tests/nextjs", 461 }, 462 ], 463 outputDir: "test-results/", 464});`},{name:"package.json",type:"file",content:`{ 465 "name": "e2e", 466 "version": "1.0.0", 467 "main": "index.js", 468 "workspaces": [ 469 "apps/*" 470 ], 471 "scripts": { 472 "test": "playwright test", 473 "dev": "npm run dev" 474 }, 475 "keywords": [], 476 "author": "", 477 "license": "ISC", 478 "description": "", 479 "devDependencies": { 480 "@playwright/test": "^1.49.0", 481 "@types/node": "^22.5.0", 482 "start-server-and-test": "^2.0.10" 483 }, 484 "dependencies": { 485 "@currents/playwright": "^1.9.4", 486 "dotenv": "^16.4.5", 487 "simple-git": "^3.27.0" 488 } 489}`}],L=a.forwardRef(({className:e,children:t,...o},r)=>(0,s.jsx)("div",{ref:r,className:(0,i.cn)("relative overflow-hidden",e),...o,children:(0,s.jsx)("div",{className:"h-full w-full overflow-auto scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent",children:t})}));L.displayName="ScrollArea",a.forwardRef(({className:e,orientation:t="vertical",...o},r)=>(0,s.jsx)("div",{ref:r,className:(0,i.cn)("flex touch-none select-none transition-colors","vertical"===t&&"h-full w-2.5 border-l border-l-transparent p-[1px]","horizontal"===t&&"h-2.5 w-full border-t border-t-transparent p-[1px]",e),...o,children:(0,s.jsx)("div",{className:"relative flex-1 rounded-full bg-border"})})).displayName="ScrollBar";var D=o(55265),_=o(31119);function P({files:e,activeTab:t,onFileClick:o}){let r=(e,a=0)=>e.map((e,n)=>(0,s.jsxs)("div",{children:[(0,s.jsxs)("button",{onClick:()=>o(e),className:(0,i.cn)("w-full flex items-center gap-2 px-3 py-1.5 text-sm hover:bg-[var(--color-editor-hover)] transition-colors text-left",t===e.name&&"bg-[var(--color-editor-hover)]"),style:{paddingLeft:`${12*a+12}px`},children:["folder"===e.type?(0,s.jsx)(D.A,{className:"w-4 h-4 text-blue-400 flex-shrink-0"}):(0,s.jsx)(_.A,{className:"w-4 h-4 text-[var(--color-editor-text-muted)] flex-shrink-0"}),(0,s.jsx)("span",{className:"text-[var(--color-editor-text)] truncate",children:e.name})]}),e.children&&r(e.children,a+1)]},`${e.name}-${n}`));return(0,s.jsxs)("div",{className:"bg-[var(--color-editor-sidebar-bg)] border-r border-[var(--color-editor-border)] flex flex-col flex-shrink-0 w-full min-w-0",children:[(0,s.jsx)("div",{className:"px-3 h-[36px] flex items-center border-b border-[var(--color-editor-border)]",children:(0,s.jsx)("h3",{className:"text-xs font-semibold text-[var(--color-editor-text)] uppercase tracking-wide",children:"Explorer"})}),(0,s.jsx)(L,{className:"flex-1",children:(0,s.jsx)("div",{className:"py-1",children:r(e)})})]})}var O=o(70501);function B({tabs:e,activeTab:t,onTabClick:o,onCloseTab:r}){return 0===e.length?null:(0,s.jsx)("div",{className:"flex items-center bg-[var(--color-editor-tab-bg)] border-b border-[var(--color-editor-border)] overflow-x-auto",children:e.map(e=>(0,s.jsxs)("button",{onClick:()=>o(e.name),className:(0,i.cn)("flex items-center gap-2 px-4 py-2 text-sm border-r border-[var(--color-editor-border)] hover:bg-[var(--color-editor-hover)] transition-colors group",t===e.name?"bg-[var(--color-editor-tab-active-bg)] text-[var(--color-editor-text)]":"text-[var(--color-editor-text-muted)]"),children:[(0,s.jsx)(_.A,{className:"w-3.5 h-3.5 flex-shrink-0"}),(0,s.jsx)("span",{className:"truncate max-w-[120px]",children:e.name}),(0,s.jsx)("a",{role:"button",onClick:t=>r(e.name,t),className:"opacity-0 group-hover:opacity-100 hover:bg-[var(--color-editor-border)] rounded p-0.5 transition-opacity",children:(0,s.jsx)(O.A,{className:"w-3 h-3"})})]},e.name))})}var M=o(58984);function z({demoFlowId:e,defaultOpenFile:t}){let o=function(){let[e,t]=a.useState(void 0);return a.useEffect(()=>{let e=window.matchMedia("(max-width: 767px)"),o=()=>{t(window.innerWidth<768)};return e.addEventListener("change",o),t(window.innerWidth<768),()=>e.removeEventListener("change",o)},[]),!!e}(),{activeMobilePanel:r,setActiveMobilePanel:c,openTabs:d,setOpenTabs:u,activeTab:p,setActiveTab:m,messages:f,setMessages:h,inputValue:g,setInputValue:x,currentPrompt:y,setCurrentPrompt:b,isDemoRunning:v,setIsDemoRunning:w,editorLoaded:k,setEditorLoaded:T,editorError:j,fileTreeWidth:C,chatSidebarWidth:N,diffFileName:S,setDiffFileName:R,editorRef:L,monacoRef:D,handleFileClick:_,handleCloseTab:O,handleSendMessage:W,handleFileTreeResize:V,handleChatSidebarResize:U}=function(e){let[t,o]=(0,a.useState)(()=>[]),[s,r]=(0,a.useState)(e||null),[i,n]=(0,a.useState)([]),[l,c]=(0,a.useState)(""),[d,u]=(0,a.useState)(null),[p,m]=(0,a.useState)(!1),[f,h]=(0,a.useState)(!1),[g,x]=(0,a.useState)(null),[y,b]=(0,a.useState)(224),[v,w]=(0,a.useState)(384),[k,T]=(0,a.useState)(null),[j,C]=(0,a.useState)("chat"),N=(0,a.useRef)(null);return{openTabs:t,setOpenTabs:o,activeTab:s,setActiveTab:r,messages:i,setMessages:n,inputValue:l,setInputValue:c,currentPrompt:d,setCurrentPrompt:u,isDemoRunning:p,setIsDemoRunning:m,editorLoaded:f,setEditorLoaded:h,editorError:g,setEditorError:x,fileTreeWidth:y,chatSidebarWidth:v,diffFileName:k,setDiffFileName:T,activeMobilePanel:j,setActiveMobilePanel:C,editorRef:N,monacoRef:(0,a.useRef)(null),handleFileClick:e=>{console.log("[v0] File clicked:",e.name,"Type:",e.type),e.content&&(t.find(t=>t.name===e.name)?console.log("[v0] Tab already open:",e.name):(console.log("[v0] Opening new tab:",e.name),o([...t,{name:e.name,content:e.content}])),r(e.name),C("editor"))},handleCloseTab:(e,a)=>{a.stopPropagation();let i=t.filter(t=>t.name!==e);o(i),k===e&&T(null),s===e&&r(i.length>0?i[i.length-1].name:null)},handleSendMessage:()=>{!l.trim()||p||(n([...i,{role:"user",content:l}]),c(""),setTimeout(()=>{let e={role:"assistant",content:"I am not programmed to reply prompts, as I am just a demo. To see our real MCP server in action, install @currents/mcp to your IDE of choice. Head to https://docs.currents.dev/guides/mcp-server to learn more.",showActions:!0};n(t=>[...t,e])},1e3))},handleFileTreeResize:e=>{b(t=>Math.max(150,Math.min(500,t+e)))},handleChatSidebarResize:e=>{w(t=>(console.log("handleChatSidebarResize",Math.max(250,Math.min(600,t-e))),Math.max(250,Math.min(600,t-e))))}}}(t);(0,a.useEffect)(()=>
489{if(t&&0===d.length){let e=(t,o)=>{for(let s of t){if("file"===s.type&&s.name===o)return s;if(s.children){let t=e(s.children,o);if(t)return t}}return null},o=e(A,t);o&&o.content&&(u([{name:o.name,content:o.content}]),m(o.name))}},[t,d.length,u,m]);let $=(0,a.useRef)(null),{handleActionClick:K}=function({demoFlowId:e,demoFlows:t,sampleFiles:o,isDemoRunning:s,setIsDemoRunning:r,setCurrentPrompt:i,setMessages:n,setOpenTabs:l,setActiveTab:c,setDiffFileName:d,monacoRef:u,diffEditorContainerRef:p,diffEditorRef:m}){let f=(0,a.useRef)(!1),h=(0,a.useCallback)(async(e,t=15)=>new Promise(o=>{let s="",r=0,a=setInterval(()=>{if(r<e.length){let t=Math.floor(3*Math.random())+1;s+=e.slice(r,r+t),r+=t,n(e=>{let t=[...e],o=t[t.length-1];return o&&o.isStreaming&&(o.content=s),t})}else clearInterval(a),n(e=>{let t=[...e],o=t[t.length-1];return o&&(o.isStreaming=!1),t}),o()},t)}),[n]),g=(0,a.useCallback)(async e=>{if(!s){for(let t of(r(!0),i(e.prompt),d(null),e.steps))if("text"===t.type||"askUser"===t.type)n(e=>[...e,{role:"assistant",content:"",isStreaming:!0,showActions:"askUser"===t.type}]),await h(t.content||"",t.delay),await new Promise(e=>setTimeout(e,300));else if("tool"===t.type)n(e=>{let o=[...e],s=o[o.length-1];return s&&"assistant"===s.role&&(s.toolCalls||(s.toolCalls=[]),s.toolCalls.push({id:t.toolId||`tool-${Date.now()}`,name:t.toolName||"unknown",status:"loading"})),o}),await new Promise(e=>setTimeout(e,t.delay||1500)),n(e=>{let o=[...e],s=o[o.length-1];if(s&&s.toolCalls){let e=s.toolCalls.find(e=>e.id===t.toolId);e&&(e.status="complete")}return o}),await new Promise(e=>setTimeout(e,300));else if("openFile"===t.type){if(t.fileName){let e=o=>{for(let s of o){if("file"===s.type&&s.name===t.fileName)return s;if(s.children){let t=e(s.children);if(t)return t}}return null},s=e(o);s&&s.content&&await new Promise(e=>{l(e=>e.find(e=>e.name===s.name)?(console.log("[v0] Tab already open:",s.name),e):(console.log("[v0] Opening new tab:",s.name),[...e,{name:s.name,content:s.content}])),c(s.name),setTimeout(e,100)})}await new Promise(e=>setTimeout(e,t.delay||800))}else if("editFile"===t.type)if(console.log("[v0] EditFile step:",t.fileName,"New content length:",t.newContent?.length),t.fileName&&t.newContent){let e=o=>{for(let s of o){if("file"===s.type&&s.name===t.fileName)return s;if(s.children){let t=e(s.children);if(t)return t}}return null},s=e(o);if(!s||!s.content){console.log("[v0] File not found in file tree:",t.fileName);continue}await new Promise(e=>{l(e=>e.find(e=>e.name===s.name)?e:(console.log("[v0] Adding file to tabs for edit:",s.name),[...e,{name:s.name,content:s.content}])),c(s.name),setTimeout(e,100)});let r=await new Promise(e=>{l(t=>(e(t),t))}),a=r.findIndex(e=>e.name===t.fileName);if(console.log("[v0] Tab index after update:",a,"Open tabs:",r.map(e=>e.name)),-1!==a){let e=r[a].content;if(console.log("[v0] Original content length:",e.length),t.showDiff&&u.current&&p.current){console.log("[v0] Creating diff editor - Monaco available:",!!u.current,"Container available:",!!p.current),d(t.fileName),await new Promise(e=>setTimeout(e,50));try{m.current&&(m.current.dispose(),m.current=null);let o=u.current.editor.createDiffEditor(p.current,{theme:"vs-dark-custom",fontSize:14,fontFamily:"var(--font-geist-mono), monospace",minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,renderSideBySide:!0,readOnly:!0,originalEditable:!1,lineNumbersMinChars:3,wordWrap:"on"});m.current=o,console.log("[v0] Diff editor instance created");let s=window.monaco,r=s.editor.createModel(e,"typescript"),a=s.editor.createModel(t.newContent,"typescript");o.setModel({original:r,modified:a}),console.log("[v0] Diff models set successfully - diff will remain visible for",t.fileName),l(e=>{let o=[...e],s=o.findIndex(e=>e.name===t.fileName);return -1!==s&&(o[s]={...o[s],content:t.newContent}),o})}catch(e){console.error("[v0] Error creating diff editor:",e),l(e=>{let o=[...e],s=o.findIndex(e=>e.name===t.fileName);return -1!==s&&(o[s]={...o[s],content:t.newContent}),o}),d(null)}}else console.log("[v0] Updating content without diff - showDiff:",t.showDiff,"Monaco available:",!!u.current,"Container available:",!!p.current),l(e=>{let o=[...e],s=o.findIndex(e=>e.name===t.fileName);return -1!==s&&(o[s]={...o[s],content:t.newContent}),o}),await new Promise(e=>setTimeout(e,t.delay||800))}else console.log("[v0] Tab still not found after adding:",t.fileName)}else console.log("[v0] Missing fileName or newContent for editFile step");r(!1)}},[s,r,i,d,n,l,c,o,u,p,m,h]),x=(0,a.useCallback)(async e=>{let o=t.find(t=>
489t.id===e);o?(n(e=>[...e,{role:"user",content:`User prompt: ${o.prompt}`,isStreaming:!1}]),await g(o)):console.error(`Demo flow with id "${e}" not found`)},[t,n,g]);return(0,a.useEffect)(()=>{if(f.current)return;let o=setTimeout(()=>{if(f.current=!0,e){let o=t.find(t=>t.id===e);o&&g(o)}else g(t[0])},500);return()=>clearTimeout(o)},[e,t]),{runDemoFlow:g,handleActionClick:x}}({demoFlowId:e,demoFlows:F,sampleFiles:A,isDemoRunning:v,setIsDemoRunning:w,setCurrentPrompt:b,setMessages:h,setOpenTabs:u,setActiveTab:m,setDiffFileName:R,monacoRef:D,diffEditorContainerRef:$,diffEditorRef:(0,a.useRef)(null)});return(0,s.jsxs)("div",{className:"w-full h-[600px] bg-[var(--color-editor-bg)] rounded-lg overflow-hidden border border-[var(--color-editor-border)] flex flex-col font-sans min-w-0",children:[(0,s.jsxs)("div",{className:"md:hidden flex items-center border-b border-[var(--color-editor-border)] bg-[var(--color-editor-sidebar-bg)]",children:[(0,s.jsxs)("button",{onClick:()=>c("files"),className:(0,i.cn)("flex-1 flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium transition-colors","files"===r?"bg-[var(--color-editor-tab-active-bg)] text-[var(--color-editor-text)] border-b-2 border-blue-500":"text-[var(--color-editor-text-muted)] hover:text-[var(--color-editor-text)]"),children:[(0,s.jsx)(l.dsF,{className:"w-4 h-4"}),(0,s.jsx)("span",{children:"Files"})]}),(0,s.jsxs)("button",{onClick:()=>c("editor"),className:(0,i.cn)("flex-1 flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium transition-colors","editor"===r?"bg-[var(--color-editor-tab-active-bg)] text-[var(--color-editor-text)] border-b-2 border-blue-500":"text-[var(--color-editor-text-muted)] hover:text-[var(--color-editor-text)]"),children:[(0,s.jsx)(l.loI,{className:"w-4 h-4"}),(0,s.jsx)("span",{children:"Editor"})]}),(0,s.jsxs)("button",{onClick:()=>c("chat"),className:(0,i.cn)("flex-1 flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium transition-colors","chat"===r?"bg-[var(--color-editor-tab-active-bg)] text-[var(--color-editor-text)] border-b-2 border-blue-500":"text-[var(--color-editor-text-muted)] hover:text-[var(--color-editor-text)]"),children:[(0,s.jsx)(M.A,{className:"w-4 h-4"}),(0,s.jsx)("span",{children:"Chat"})]})]}),(0,s.jsxs)("div",{className:"flex-1 flex md:flex-row overflow-hidden min-w-0",children:[(0,s.jsx)("div",{className:(0,i.cn)("md:flex min-w-0","files"===r?"flex":"hidden"),style:{width:"files"===r?"100%":`${C}px`,maxWidth:"100%"},children:(0,s.jsx)(P,{files:A,activeTab:p,onFileClick:_})}),d.length>0&&(0,s.jsx)(n,{onResize:V,className:"hidden md:block"}),(0,s.jsxs)("div",{className:(0,i.cn)("flex-1 flex flex-col min-w-0","md:flex","editor"===r?"flex":"hidden",0===d.length&&"md:hidden md:absolute md:pointer-events-none"),children:[(0,s.jsx)(B,{tabs:d,activeTab:p,onTabClick:m,onCloseTab:O}),(0,s.jsx)(I,{activeTab:p,tabs:d,editorLoaded:k,editorError:j,diffFileName:S,onEditorReady:(e,t)=>{L.current=e,D.current=t,T(!0)},diffEditorContainerRef:$})]}),d.length>0&&(0,s.jsx)(n,{onResize:U,className:"hidden md:block"}),(0,s.jsx)("div",{className:(0,i.cn)("md:flex min-w-0","chat"===r?"flex":"hidden"),style:{width:o&&"chat"===r?"100%":0===d.length?"auto":`${N}px`,maxWidth:"100%",flex:o&&"chat"===r||0===d.length?1:void 0},children:(0,s.jsx)(E,{messages:f,inputValue:g,onInputChange:x,onSendMessage:W,currentPrompt:y,isDemoRunning:v,onActionClick:K})})]})]})}function W(){return(0,s.jsxs)("section",{className:"border-dark-100",children:[(0,s.jsx)("a",{id:"mcp"}),(0,s.jsxs)("div",{className:"container max-w-[1327px] mx-auto px-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-x-2.5 xl:mb-5 md:mb-4 mb-2.5",children:[(0,s.jsx)(r.A,{stroke:1.5,className:"text-emerald-400"}),(0,s.jsx)("div",{className:"uppercase tracking-[0.02em] font-semibold font-poppins text-emerald-400 lg:text-[16px] text-[14px] ",children:"MCP Server"})]}),(0,s.jsx)("h3",{className:" font-semibold lg:text-h3 md:text-h3mdi md:pb-6 text-h3mob font-poppins",children:"Keep Your Tests Healthy With AI"}),(0,s.jsx)("div",{className:"mb-7.5 flex justify-between gap-x-5 gap-y-4 lg:gap-y-0 w-full flex-col lg:flex-row",children:(0,s.jsx)("div",{className:" max-w-4xl text-[18px]",children:(0,s.jsx)("p",{children:"Currents MCP server empowers AI agents with rich data to better understand your tests, including historical test results and health metrics. Vibe-fix-and-unflake tests, generate reports and create AI-driven automations in CI, your terminal or editor."})})}),(0,s.jsx)("div",{className:"flex flex-colgap-8 mt-8",children:(0,s.jsx)("div",{className:"relative rounded-lg border border-dark-100 p-6 lg:p-6 w-full",style:{background:"linear-gradient(160deg, #26262b 10%, var(--tw-gradient-via, rgba(52, 211, 153, 0.5)) 30%, #26262b 90%)"},children:(0,s.jsx)(z,{})})})]})]})}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.