@zibby/core 0.1.34 → 0.1.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/agents/base.js +157 -190
  2. package/dist/backend-client.js +1 -1
  3. package/dist/constants/zibby-scratch.js +1 -1
  4. package/dist/enrichment/enrichers/accessibility-enricher.js +1 -1
  5. package/dist/enrichment/index.js +2 -2
  6. package/dist/enrichment/mcp-integration.js +2 -2
  7. package/dist/enrichment/trace-text-enricher.js +2 -2
  8. package/dist/framework/agents/assistant-strategy.js +3 -3
  9. package/dist/framework/agents/claude-strategy.js +53 -54
  10. package/dist/framework/agents/codex-strategy.js +1 -1
  11. package/dist/framework/agents/cursor-strategy.js +51 -83
  12. package/dist/framework/agents/gemini-strategy.js +2 -2
  13. package/dist/framework/agents/index.js +131 -164
  14. package/dist/framework/agents/utils/auth-resolver.js +1 -1
  15. package/dist/framework/agents/utils/openai-proxy-formatter.js +25 -57
  16. package/dist/framework/code-generator.js +143 -176
  17. package/dist/framework/context-loader.js +1 -1
  18. package/dist/framework/function-bridge.js +2 -2
  19. package/dist/framework/graph-compiler.js +150 -183
  20. package/dist/framework/graph.js +149 -182
  21. package/dist/framework/index.js +152 -185
  22. package/dist/framework/mcp-client.js +2 -2
  23. package/dist/framework/node-registry.js +134 -167
  24. package/dist/framework/node.js +146 -179
  25. package/dist/index.js +199 -232
  26. package/dist/package.json +1 -1
  27. package/dist/runtime/generation/index.js +2 -2
  28. package/dist/runtime/generation/mcp-ref-strategy.js +1 -1
  29. package/dist/runtime/generation/stable-id-strategy.js +1 -1
  30. package/dist/runtime/verification/index.js +1 -1
  31. package/dist/runtime/verification/playwright-json-strategy.js +1 -1
  32. package/dist/tools/run-playwright-test.js +1 -1
  33. package/dist/utils/ci-setup.js +1 -1
  34. package/dist/utils/cursor-mcp-isolated-home.js +1 -1
  35. package/dist/utils/cursor-utils.js +1 -1
  36. package/dist/utils/live-frame-discovery.js +1 -1
  37. package/dist/utils/mcp-config-writer.js +1 -1
  38. package/dist/utils/post-process-events.js +2 -2
  39. package/dist/utils/repo-clone.js +1 -1
  40. package/dist/utils/result-handler.js +1 -1
  41. package/dist/utils/run-capacity-coordinator.js +2 -2
  42. package/dist/utils/run-capacity-queue.js +2 -2
  43. package/dist/utils/run-index-post-cli.js +2 -2
  44. package/dist/utils/run-registry.js +1 -1
  45. package/dist/utils/run-state-session.js +1 -1
  46. package/dist/utils/trace-parser.js +1 -1
  47. package/dist/utils/video-organizer.js +1 -1
  48. package/package.json +1 -1
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/core",
3
- "version": "0.1.34",
3
+ "version": "0.1.37",
4
4
  "description": "Core test automation engine with multi-agent and multi-MCP support",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,4 +1,4 @@
1
- var d=class{async generate(a){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(a){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as w,writeFileSync as G}from"fs";var b=class extends d{constructor(){super("mcp-ref","MCP Reference Replay (Exact 1:1)",200)}canGenerate(a){let t=a.eventsPath||`${a.sessionPath}/execute_live/events.json`;try{return JSON.parse(w(t,"utf-8")).some(p=>p.data?.params?.element)?(console.log("[MCPRefStrategy] \u2705 MCP element descriptions available"),!0):(console.log("[MCPRefStrategy] \u274C No MCP element descriptions found in events"),!1)}catch(s){return console.log("[MCPRefStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"MCP Reference Replay (Exact 1:1)"}getPriority(){return 200}async generate(a){let{testFilePath:t,sessionPath:s,state:o}=a,p=`${s}/execute_live/events.json`,x=o?.title||"Generated Test";console.log("[MCPRefStrategy] \u{1F3AF} Generating test using MCP element descriptions (1:1 replay)"),console.log(`[MCPRefStrategy] events: ${p}`),console.log(`[MCPRefStrategy] output: ${t}`);let u=JSON.parse(w(p,"utf-8")).filter(n=>["navigate","type","fill","click","select_option"].includes(n.type)),e=`import { test, expect } from '@playwright/test';
1
+ var d=class{async generate(a){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(a){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as w,writeFileSync as G}from"node:fs";var b=class extends d{constructor(){super("mcp-ref","MCP Reference Replay (Exact 1:1)",200)}canGenerate(a){let t=a.eventsPath||`${a.sessionPath}/execute_live/events.json`;try{return JSON.parse(w(t,"utf-8")).some(p=>p.data?.params?.element)?(console.log("[MCPRefStrategy] \u2705 MCP element descriptions available"),!0):(console.log("[MCPRefStrategy] \u274C No MCP element descriptions found in events"),!1)}catch(s){return console.log("[MCPRefStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"MCP Reference Replay (Exact 1:1)"}getPriority(){return 200}async generate(a){let{testFilePath:t,sessionPath:s,state:o}=a,p=`${s}/execute_live/events.json`,x=o?.title||"Generated Test";console.log("[MCPRefStrategy] \u{1F3AF} Generating test using MCP element descriptions (1:1 replay)"),console.log(`[MCPRefStrategy] events: ${p}`),console.log(`[MCPRefStrategy] output: ${t}`);let u=JSON.parse(w(p,"utf-8")).filter(n=>["navigate","type","fill","click","select_option"].includes(n.type)),e=`import { test, expect } from '@playwright/test';
2
2
  `;e+=`import { ZibbyRuntime } from '@zibby/core';
3
3
 
4
4
  `,e+=`test('${x}', async ({ page }) => {
@@ -38,7 +38,7 @@ var d=class{async generate(a){throw new Error("TestGenerationStrategy.generate()
38
38
  `,e+=` });
39
39
 
40
40
  `}}return e+=`});
41
- `,G(t,e),console.log(`[MCPRefStrategy] \u2705 Generated test with ${u.length} actions using MCP descriptions`),{success:!0,testPath:t,method:"MCP Reference Replay (1:1)",actionsGenerated:u.length}}_extractRole(a){let t=a.toLowerCase();return t.includes("button")?"button":t.includes("textbox")?"textbox":t.includes("link")?"link":t.includes("checkbox")?"checkbox":t.includes("radio")?"radio":t.includes("combobox")?"combobox":t.includes("heading")?"heading":"button"}_extractName(a){return a.replace(/\s+(button|textbox|link|checkbox|radio|combobox)$/i,"").trim()}_escapeRegex(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}_escapeString(a){return a.replace(/'/g,"\\'").replace(/\n/g,"\\n")}};import{readFileSync as R,writeFileSync as N}from"fs";var h=class extends d{constructor(){super("stable-id","Stable ID Injection (Experimental)",300)}canGenerate(a){let t=a.eventsPath||`${a.sessionPath}/execute_live/events.json`;try{return JSON.parse(R(t,"utf-8")).some(p=>p.stableId||p.data?.stableId)?(console.log("[StableIdStrategy] \u2705 Stable IDs available"),!0):(console.log("[StableIdStrategy] \u274C No stable IDs found in events"),!1)}catch(s){return console.log("[StableIdStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"Stable ID Injection (Experimental)"}getPriority(){return 300}async generate(a){let{testFilePath:t,sessionPath:s,state:o}=a,p=`${s}/execute_live/events.json`,x=o?.title||"Generated Test";console.log("[StableIdStrategy] \u{1F3AF} Generating test using stable IDs"),console.log(`[StableIdStrategy] events: ${p}`),console.log(`[StableIdStrategy] output: ${t}`);let u=JSON.parse(R(p,"utf-8")).filter(m=>["navigate","type","fill","click","select_option","select"].includes(m.type)),e=`import { test, expect } from '@playwright/test';
41
+ `,G(t,e),console.log(`[MCPRefStrategy] \u2705 Generated test with ${u.length} actions using MCP descriptions`),{success:!0,testPath:t,method:"MCP Reference Replay (1:1)",actionsGenerated:u.length}}_extractRole(a){let t=a.toLowerCase();return t.includes("button")?"button":t.includes("textbox")?"textbox":t.includes("link")?"link":t.includes("checkbox")?"checkbox":t.includes("radio")?"radio":t.includes("combobox")?"combobox":t.includes("heading")?"heading":"button"}_extractName(a){return a.replace(/\s+(button|textbox|link|checkbox|radio|combobox)$/i,"").trim()}_escapeRegex(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}_escapeString(a){return a.replace(/'/g,"\\'").replace(/\n/g,"\\n")}};import{readFileSync as R,writeFileSync as N}from"node:fs";var h=class extends d{constructor(){super("stable-id","Stable ID Injection (Experimental)",300)}canGenerate(a){let t=a.eventsPath||`${a.sessionPath}/execute_live/events.json`;try{return JSON.parse(R(t,"utf-8")).some(p=>p.stableId||p.data?.stableId)?(console.log("[StableIdStrategy] \u2705 Stable IDs available"),!0):(console.log("[StableIdStrategy] \u274C No stable IDs found in events"),!1)}catch(s){return console.log("[StableIdStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"Stable ID Injection (Experimental)"}getPriority(){return 300}async generate(a){let{testFilePath:t,sessionPath:s,state:o}=a,p=`${s}/execute_live/events.json`,x=o?.title||"Generated Test";console.log("[StableIdStrategy] \u{1F3AF} Generating test using stable IDs"),console.log(`[StableIdStrategy] events: ${p}`),console.log(`[StableIdStrategy] output: ${t}`);let u=JSON.parse(R(p,"utf-8")).filter(m=>["navigate","type","fill","click","select_option","select"].includes(m.type)),e=`import { test, expect } from '@playwright/test';
42
42
  `;e+=`import { StableIdRuntime } from '@zibby/core';
43
43
 
44
44
  `,e+=`test('${x}', async ({ page }) => {
@@ -1,4 +1,4 @@
1
- var p=class{async generate(n){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(n){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as h,writeFileSync as R}from"fs";var x=class extends p{constructor(){super("mcp-ref","MCP Reference Replay (Exact 1:1)",200)}canGenerate(n){let a=n.eventsPath||`${n.sessionPath}/execute_live/events.json`;try{return JSON.parse(h(a,"utf-8")).some(l=>l.data?.params?.element)?(console.log("[MCPRefStrategy] \u2705 MCP element descriptions available"),!0):(console.log("[MCPRefStrategy] \u274C No MCP element descriptions found in events"),!1)}catch(i){return console.log("[MCPRefStrategy] \u274C Failed to read events:",i.message),!1}}getName(){return"MCP Reference Replay (Exact 1:1)"}getPriority(){return 200}async generate(n){let{testFilePath:a,sessionPath:i,state:g}=n,l=`${i}/execute_live/events.json`,$=g?.title||"Generated Test";console.log("[MCPRefStrategy] \u{1F3AF} Generating test using MCP element descriptions (1:1 replay)"),console.log(`[MCPRefStrategy] events: ${l}`),console.log(`[MCPRefStrategy] output: ${a}`);let u=JSON.parse(h(l,"utf-8")).filter(t=>["navigate","type","fill","click","select_option"].includes(t.type)),e=`import { test, expect } from '@playwright/test';
1
+ var p=class{async generate(n){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(n){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as h,writeFileSync as R}from"node:fs";var x=class extends p{constructor(){super("mcp-ref","MCP Reference Replay (Exact 1:1)",200)}canGenerate(n){let a=n.eventsPath||`${n.sessionPath}/execute_live/events.json`;try{return JSON.parse(h(a,"utf-8")).some(l=>l.data?.params?.element)?(console.log("[MCPRefStrategy] \u2705 MCP element descriptions available"),!0):(console.log("[MCPRefStrategy] \u274C No MCP element descriptions found in events"),!1)}catch(i){return console.log("[MCPRefStrategy] \u274C Failed to read events:",i.message),!1}}getName(){return"MCP Reference Replay (Exact 1:1)"}getPriority(){return 200}async generate(n){let{testFilePath:a,sessionPath:i,state:g}=n,l=`${i}/execute_live/events.json`,$=g?.title||"Generated Test";console.log("[MCPRefStrategy] \u{1F3AF} Generating test using MCP element descriptions (1:1 replay)"),console.log(`[MCPRefStrategy] events: ${l}`),console.log(`[MCPRefStrategy] output: ${a}`);let u=JSON.parse(h(l,"utf-8")).filter(t=>["navigate","type","fill","click","select_option"].includes(t.type)),e=`import { test, expect } from '@playwright/test';
2
2
  `;e+=`import { ZibbyRuntime } from '@zibby/core';
3
3
 
4
4
  `,e+=`test('${$}', async ({ page }) => {
@@ -1,4 +1,4 @@
1
- var d=class{async generate(e){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(e){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as m,writeFileSync as I}from"fs";var y=class extends d{constructor(){super("stable-id","Stable ID Injection (Experimental)",300)}canGenerate(e){let a=e.eventsPath||`${e.sessionPath}/execute_live/events.json`;try{return JSON.parse(m(a,"utf-8")).some(o=>o.stableId||o.data?.stableId)?(console.log("[StableIdStrategy] \u2705 Stable IDs available"),!0):(console.log("[StableIdStrategy] \u274C No stable IDs found in events"),!1)}catch(s){return console.log("[StableIdStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"Stable ID Injection (Experimental)"}getPriority(){return 300}async generate(e){let{testFilePath:a,sessionPath:s,state:i}=e,o=`${s}/execute_live/events.json`,h=i?.title||"Generated Test";console.log("[StableIdStrategy] \u{1F3AF} Generating test using stable IDs"),console.log(`[StableIdStrategy] events: ${o}`),console.log(`[StableIdStrategy] output: ${a}`);let g=JSON.parse(m(o,"utf-8")).filter(c=>["navigate","type","fill","click","select_option","select"].includes(c.type)),n=`import { test, expect } from '@playwright/test';
1
+ var d=class{async generate(e){throw new Error("TestGenerationStrategy.generate() must be implemented")}canGenerate(e){throw new Error("TestGenerationStrategy.canGenerate() must be implemented")}getName(){throw new Error("TestGenerationStrategy.getName() must be implemented")}getPriority(){return 0}};import{readFileSync as m,writeFileSync as I}from"node:fs";var y=class extends d{constructor(){super("stable-id","Stable ID Injection (Experimental)",300)}canGenerate(e){let a=e.eventsPath||`${e.sessionPath}/execute_live/events.json`;try{return JSON.parse(m(a,"utf-8")).some(o=>o.stableId||o.data?.stableId)?(console.log("[StableIdStrategy] \u2705 Stable IDs available"),!0):(console.log("[StableIdStrategy] \u274C No stable IDs found in events"),!1)}catch(s){return console.log("[StableIdStrategy] \u274C Failed to read events:",s.message),!1}}getName(){return"Stable ID Injection (Experimental)"}getPriority(){return 300}async generate(e){let{testFilePath:a,sessionPath:s,state:i}=e,o=`${s}/execute_live/events.json`,h=i?.title||"Generated Test";console.log("[StableIdStrategy] \u{1F3AF} Generating test using stable IDs"),console.log(`[StableIdStrategy] events: ${o}`),console.log(`[StableIdStrategy] output: ${a}`);let g=JSON.parse(m(o,"utf-8")).filter(c=>["navigate","type","fill","click","select_option","select"].includes(c.type)),n=`import { test, expect } from '@playwright/test';
2
2
  `;n+=`import { StableIdRuntime } from '@zibby/core';
3
3
 
4
4
  `,n+=`test('${h}', async ({ page }) => {
@@ -1,3 +1,3 @@
1
- var c=class{async verify(t){throw new Error("TestVerificationStrategy.verify() must be implemented")}canVerify(t){throw new Error("TestVerificationStrategy.canVerify() must be implemented")}getName(){throw new Error("TestVerificationStrategy.getName() must be implemented")}getPriority(){return 0}};import{execSync as x}from"child_process";import{existsSync as w}from"fs";var l=class extends c{getName(){return"Playwright JSON Reporter"}getPriority(){return 100}canVerify(t){let{testFilePath:e}=t;return w(e)}async verify(t){let{testFilePath:e,cwd:n,timeout:m=3e4}=t;try{console.log(`\u{1F9EA} Running test: ${e}`);let a=`npx playwright test ${e} --reporter=json --timeout=${m}`,i=x(a,{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:m+1e4}),s=JSON.parse(i).stats||{};return{success:s.unexpected===0,passed:s.expected||0,failed:s.unexpected||0,error:null,errorDetails:null}}catch(a){let i=a.stdout||a.stderr||a.message;try{let o=JSON.parse(i),s=o.stats||{},r="Test execution failed";if(o.suites&&o.suites.length>0){let g=o.suites[0];if(g.specs&&g.specs.length>0){let p=g.specs[0];if(p.tests&&p.tests.length>0){let d=p.tests[0];if(d.results&&d.results.length>0){let h=d.results[0];h.error&&(r=h.error.message||r)}}}}let u=r.includes("Executable doesn't exist")||r.includes("browserType.launch")||r.includes("Please run the following command")||r.includes("npx playwright install")||i.includes("Executable doesn't exist")||i.includes("npx playwright install");return{success:!1,passed:s.expected||0,failed:s.unexpected||0,error:r,errorDetails:r,isEnvironmentError:u}}catch{let s=i.match(/Error: (.+)/),r=s?s[1]:"Test execution failed",u=r.includes("Executable doesn't exist")||r.includes("browserType.launch")||r.includes("Please run the following command")||r.includes("npx playwright install")||i.includes("Executable doesn't exist")||i.includes("npx playwright install");return{success:!1,passed:0,failed:1,error:r,errorDetails:r,isEnvironmentError:u}}}}};var f=class{constructor(){this.strategies=[new l],this.strategies.sort((t,e)=>e.getPriority()-t.getPriority())}registerStrategy(t){this.strategies.push(t),this.strategies.sort((e,n)=>n.getPriority()-e.getPriority())}async verify(t){console.log(`
1
+ var c=class{async verify(t){throw new Error("TestVerificationStrategy.verify() must be implemented")}canVerify(t){throw new Error("TestVerificationStrategy.canVerify() must be implemented")}getName(){throw new Error("TestVerificationStrategy.getName() must be implemented")}getPriority(){return 0}};import{execSync as x}from"node:child_process";import{existsSync as w}from"node:fs";var l=class extends c{getName(){return"Playwright JSON Reporter"}getPriority(){return 100}canVerify(t){let{testFilePath:e}=t;return w(e)}async verify(t){let{testFilePath:e,cwd:n,timeout:m=3e4}=t;try{console.log(`\u{1F9EA} Running test: ${e}`);let a=`npx playwright test ${e} --reporter=json --timeout=${m}`,i=x(a,{cwd:n,encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:m+1e4}),s=JSON.parse(i).stats||{};return{success:s.unexpected===0,passed:s.expected||0,failed:s.unexpected||0,error:null,errorDetails:null}}catch(a){let i=a.stdout||a.stderr||a.message;try{let o=JSON.parse(i),s=o.stats||{},r="Test execution failed";if(o.suites&&o.suites.length>0){let g=o.suites[0];if(g.specs&&g.specs.length>0){let p=g.specs[0];if(p.tests&&p.tests.length>0){let d=p.tests[0];if(d.results&&d.results.length>0){let h=d.results[0];h.error&&(r=h.error.message||r)}}}}let u=r.includes("Executable doesn't exist")||r.includes("browserType.launch")||r.includes("Please run the following command")||r.includes("npx playwright install")||i.includes("Executable doesn't exist")||i.includes("npx playwright install");return{success:!1,passed:s.expected||0,failed:s.unexpected||0,error:r,errorDetails:r,isEnvironmentError:u}}catch{let s=i.match(/Error: (.+)/),r=s?s[1]:"Test execution failed",u=r.includes("Executable doesn't exist")||r.includes("browserType.launch")||r.includes("Please run the following command")||r.includes("npx playwright install")||i.includes("Executable doesn't exist")||i.includes("npx playwright install");return{success:!1,passed:0,failed:1,error:r,errorDetails:r,isEnvironmentError:u}}}}};var f=class{constructor(){this.strategies=[new l],this.strategies.sort((t,e)=>e.getPriority()-t.getPriority())}registerStrategy(t){this.strategies.push(t),this.strategies.sort((e,n)=>n.getPriority()-e.getPriority())}async verify(t){console.log(`
2
2
  \u{1F4CB} Available verification strategies (${this.strategies.length}):`),this.strategies.forEach(e=>{let n=e.canVerify(t);console.log(` ${n?"\u2713":"\u2717"} ${e.getName()} (priority: ${e.getPriority()})`)});for(let e of this.strategies)if(e.canVerify(t))return console.log(`
3
3
  \u{1F3AF} Selected: ${e.getName()}`),e.verify(t);throw new Error("No verification strategy available for this context")}getStrategy(t){return this.strategies.find(e=>e.getName().includes(t))||null}},E=new f,$=E;export{l as PlaywrightJsonVerificationStrategy,c as TestVerificationStrategy,f as TestVerificationStrategyManager,$ as default,E as testVerificationManager};
@@ -1 +1 @@
1
- var c=class{async verify(n){throw new Error("TestVerificationStrategy.verify() must be implemented")}canVerify(n){throw new Error("TestVerificationStrategy.canVerify() must be implemented")}getName(){throw new Error("TestVerificationStrategy.getName() must be implemented")}getPriority(){return 0}};import{execSync as y}from"child_process";import{existsSync as h}from"fs";var d=class extends c{getName(){return"Playwright JSON Reporter"}getPriority(){return 100}canVerify(n){let{testFilePath:i}=n;return h(i)}async verify(n){let{testFilePath:i,cwd:g,timeout:m=3e4}=n;try{console.log(`\u{1F9EA} Running test: ${i}`);let o=`npx playwright test ${i} --reporter=json --timeout=${m}`,s=y(o,{cwd:g,encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:m+1e4}),t=JSON.parse(s).stats||{};return{success:t.unexpected===0,passed:t.expected||0,failed:t.unexpected||0,error:null,errorDetails:null}}catch(o){let s=o.stdout||o.stderr||o.message;try{let r=JSON.parse(s),t=r.stats||{},e="Test execution failed";if(r.suites&&r.suites.length>0){let a=r.suites[0];if(a.specs&&a.specs.length>0){let u=a.specs[0];if(u.tests&&u.tests.length>0){let p=u.tests[0];if(p.results&&p.results.length>0){let x=p.results[0];x.error&&(e=x.error.message||e)}}}}let l=e.includes("Executable doesn't exist")||e.includes("browserType.launch")||e.includes("Please run the following command")||e.includes("npx playwright install")||s.includes("Executable doesn't exist")||s.includes("npx playwright install");return{success:!1,passed:t.expected||0,failed:t.unexpected||0,error:e,errorDetails:e,isEnvironmentError:l}}catch{let t=s.match(/Error: (.+)/),e=t?t[1]:"Test execution failed",l=e.includes("Executable doesn't exist")||e.includes("browserType.launch")||e.includes("Please run the following command")||e.includes("npx playwright install")||s.includes("Executable doesn't exist")||s.includes("npx playwright install");return{success:!1,passed:0,failed:1,error:e,errorDetails:e,isEnvironmentError:l}}}}},T=d;export{d as PlaywrightJsonVerificationStrategy,T as default};
1
+ var c=class{async verify(n){throw new Error("TestVerificationStrategy.verify() must be implemented")}canVerify(n){throw new Error("TestVerificationStrategy.canVerify() must be implemented")}getName(){throw new Error("TestVerificationStrategy.getName() must be implemented")}getPriority(){return 0}};import{execSync as y}from"node:child_process";import{existsSync as h}from"node:fs";var d=class extends c{getName(){return"Playwright JSON Reporter"}getPriority(){return 100}canVerify(n){let{testFilePath:i}=n;return h(i)}async verify(n){let{testFilePath:i,cwd:g,timeout:m=3e4}=n;try{console.log(`\u{1F9EA} Running test: ${i}`);let o=`npx playwright test ${i} --reporter=json --timeout=${m}`,s=y(o,{cwd:g,encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:m+1e4}),t=JSON.parse(s).stats||{};return{success:t.unexpected===0,passed:t.expected||0,failed:t.unexpected||0,error:null,errorDetails:null}}catch(o){let s=o.stdout||o.stderr||o.message;try{let r=JSON.parse(s),t=r.stats||{},e="Test execution failed";if(r.suites&&r.suites.length>0){let a=r.suites[0];if(a.specs&&a.specs.length>0){let u=a.specs[0];if(u.tests&&u.tests.length>0){let p=u.tests[0];if(p.results&&p.results.length>0){let x=p.results[0];x.error&&(e=x.error.message||e)}}}}let l=e.includes("Executable doesn't exist")||e.includes("browserType.launch")||e.includes("Please run the following command")||e.includes("npx playwright install")||s.includes("Executable doesn't exist")||s.includes("npx playwright install");return{success:!1,passed:t.expected||0,failed:t.unexpected||0,error:e,errorDetails:e,isEnvironmentError:l}}catch{let t=s.match(/Error: (.+)/),e=t?t[1]:"Test execution failed",l=e.includes("Executable doesn't exist")||e.includes("browserType.launch")||e.includes("Please run the following command")||e.includes("npx playwright install")||s.includes("Executable doesn't exist")||s.includes("npx playwright install");return{success:!1,passed:0,failed:1,error:e,errorDetails:e,isEnvironmentError:l}}}}},T=d;export{d as PlaywrightJsonVerificationStrategy,T as default};
@@ -1,4 +1,4 @@
1
- import{spawn as T}from"child_process";import{existsSync as S}from"fs";import{dirname as k,resolve as $,relative as I}from"path";var m=new Map,l=8,M={name:"run_playwright_test",description:`Run a Playwright test file and return results. Use this after writing a test to verify it works. If it fails, fix the issues and run again. Maximum ${l} attempts per session.`,inputSchema:{type:"object",properties:{scriptPath:{type:"string",description:"Path to the Playwright test file (e.g., tests/login.spec.js)"}},required:["scriptPath"]},async execute({scriptPath:o},i){let x=`${i?.sessionId||"default"}:${o}`,t=(m.get(x)||0)+1;if(m.set(x,t),t>l)return{success:!1,executionCount:t,maxReached:!0,error:`Maximum ${l} executions reached. Stop retrying and return your best result.`};let h=i?.projectRoot||process.cwd(),e=$(h,o),y=I(h,e);return y.startsWith("..")||$(e)!==e&&y.includes("..")?{success:!1,executionCount:t,error:"Path traversal detected: scriptPath must be within the project root."}:S(e)?new Promise(d=>{let j=k(e),u=T("npx",["playwright","test",e,"--reporter=line"],{cwd:h,env:{...process.env,FORCE_COLOR:"0"}}),c="",f="";u.stdout.on("data",s=>{c+=s.toString()}),u.stderr.on("data",s=>{f+=s.toString()});let w=setTimeout(()=>{u.kill("SIGTERM"),d({success:!1,executionCount:t,error:"Test timed out after 60 seconds",stdout:c.slice(-2e3),stderr:f.slice(-1e3)})},6e4);u.on("close",s=>{clearTimeout(w);let p=`${c}
1
+ import{spawn as T}from"node:child_process";import{existsSync as S}from"node:fs";import{dirname as k,resolve as $,relative as I}from"node:path";var m=new Map,l=8,M={name:"run_playwright_test",description:`Run a Playwright test file and return results. Use this after writing a test to verify it works. If it fails, fix the issues and run again. Maximum ${l} attempts per session.`,inputSchema:{type:"object",properties:{scriptPath:{type:"string",description:"Path to the Playwright test file (e.g., tests/login.spec.js)"}},required:["scriptPath"]},async execute({scriptPath:o},i){let x=`${i?.sessionId||"default"}:${o}`,t=(m.get(x)||0)+1;if(m.set(x,t),t>l)return{success:!1,executionCount:t,maxReached:!0,error:`Maximum ${l} executions reached. Stop retrying and return your best result.`};let h=i?.projectRoot||process.cwd(),e=$(h,o),y=I(h,e);return y.startsWith("..")||$(e)!==e&&y.includes("..")?{success:!1,executionCount:t,error:"Path traversal detected: scriptPath must be within the project root."}:S(e)?new Promise(d=>{let j=k(e),u=T("npx",["playwright","test",e,"--reporter=line"],{cwd:h,env:{...process.env,FORCE_COLOR:"0"}}),c="",f="";u.stdout.on("data",s=>{c+=s.toString()}),u.stderr.on("data",s=>{f+=s.toString()});let w=setTimeout(()=>{u.kill("SIGTERM"),d({success:!1,executionCount:t,error:"Test timed out after 60 seconds",stdout:c.slice(-2e3),stderr:f.slice(-1e3)})},6e4);u.on("close",s=>{clearTimeout(w);let p=`${c}
2
2
  ${f}`.split(`
3
3
  `),g="",C=null;for(let a=0;a<p.length;a++){let r=p[a];if(r.includes("Error:")||r.includes("error:")||r.includes("\u2718")){g+=`${r}
4
4
  `;for(let n=a+1;n<Math.min(a+5,p.length);n++)g+=`${p[n]}
@@ -1,4 +1,4 @@
1
- var u=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,o)=>(typeof require<"u"?require:t)[o]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});import{spawn as i}from"child_process";import{readFileSync as d,writeFileSync as f,existsSync as a}from"fs";import{homedir as l}from"os";import{join as c}from"path";async function P(){let r=c(l(),".local/share/cursor-agent/versions");if(!a(r))throw new Error(`cursor-agent not found at ${r}. Please install cursor-agent first.`);return console.log(`\u{1F527} Patching cursor-agent for CI/CD...
1
+ var u=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,o)=>(typeof require<"u"?require:t)[o]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});import{spawn as i}from"node:child_process";import{readFileSync as d,writeFileSync as f,existsSync as a}from"node:fs";import{homedir as l}from"node:os";import{join as c}from"node:path";async function P(){let r=c(l(),".local/share/cursor-agent/versions");if(!a(r))throw new Error(`cursor-agent not found at ${r}. Please install cursor-agent first.`);return console.log(`\u{1F527} Patching cursor-agent for CI/CD...
2
2
  `),new Promise((t,o)=>{let e=c(__dirname,"../../scripts/patch-cursor-mcp.py");if(!a(e)){o(new Error("Patch script not found"));return}let n=i("python3",[e],{stdio:"inherit"});n.on("close",s=>{s===0?t({success:!0}):o(new Error(`Patch failed with code ${s}`))}),n.on("error",s=>{o(s)})})}function S(){let r=c(l(),".local/share/cursor-agent/versions");if(!a(r))return{patched:!1,installed:!1};try{let t=u("fs").readdirSync(r);if(t.length===0)return{patched:!1,installed:!1};let o=t.sort().reverse()[0],e=c(r,o,"index.js");return a(e)?{patched:d(e,"utf-8").includes("AUTO-APPROVE MCP TOOLS FOR CI/CD"),installed:!0,path:e}:{patched:!1,installed:!1}}catch(t){return{patched:!1,installed:!1,error:t.message}}}async function x(r){return console.log(`\u{1F511} Getting MCP approval keys...
3
3
  `),new Promise((t,o)=>{let e=i("cursor-agent",["mcp","list"],{cwd:r,stdio:"pipe"}),n="";e.stdout.on("data",s=>{n+=s.toString(),process.stdout.write(s)}),e.stderr.on("data",s=>{process.stderr.write(s)}),e.on("close",s=>{if(s===0){let p=h(n);t({success:!0,keys:p,output:n})}else o(new Error(`Failed to get approval keys (exit code ${s})`))}),e.on("error",s=>{o(s)})})}function h(r){let t={},o=/🔑 APPROVAL KEY:\s+(\S+)\s+=>\s+(\S+)/g,e;for(;(e=o.exec(r))!==null;)t[e[1]]=e[2];return t}function A(r,t){let o=c(r,".cursor/projects"),e=c(o,"mcp-approvals.json");f(e,JSON.stringify(t,null,2)),console.log(`
4
4
  \u2705 Saved approval keys to: ${e}
@@ -1 +1 @@
1
- import{copyFileSync as m,existsSync as c,lstatSync as p,mkdirSync as a,rmSync as l,symlinkSync as S,unlinkSync as L}from"fs";import{join as o}from"path";import{homedir as _}from"os";import{randomBytes as C}from"crypto";var b=["cli-config.json","config.json","auth.json","argv.json"];function B(r){return!(!r||typeof r!="string"||process.env.ZIBBY_CURSOR_USE_GLOBAL_MCP==="1"||process.env.ZIBBY_CURSOR_USE_GLOBAL_MCP==="true")}function O(r){let t=o(r||process.cwd(),".zibby","tmp");a(t,{recursive:!0});let y=`${process.pid}-${Date.now()}-${C(4).toString("hex")}`,n=o(t,`cursor-agent-home-${y}`),s=o(n,".cursor");a(s,{recursive:!0});let i=_(),u=o(i,".cursor");if(c(u))for(let e of b){let f=o(u,e);if(c(f))try{m(f,o(s,e))}catch{}}if(process.platform==="darwin"){let e=o(i,"Library");if(c(e))try{S(e,o(n,"Library"))}catch{}}return n}function k(r){if(!(!r||typeof r!="string"))try{let t=o(r,"Library");try{p(t).isSymbolicLink()&&L(t)}catch{}l(r,{recursive:!0,force:!0})}catch{}}export{b as CURSOR_HOME_DOT_FILES,O as createIsolatedCursorAgentHome,k as removeIsolatedCursorAgentHome,B as shouldUseIsolatedCursorMcpHome};
1
+ import{copyFileSync as m,existsSync as c,lstatSync as p,mkdirSync as a,rmSync as l,symlinkSync as S,unlinkSync as L}from"node:fs";import{join as o}from"node:path";import{homedir as _}from"node:os";import{randomBytes as C}from"node:crypto";var b=["cli-config.json","config.json","auth.json","argv.json"];function B(r){return!(!r||typeof r!="string"||process.env.ZIBBY_CURSOR_USE_GLOBAL_MCP==="1"||process.env.ZIBBY_CURSOR_USE_GLOBAL_MCP==="true")}function O(r){let t=o(r||process.cwd(),".zibby","tmp");a(t,{recursive:!0});let y=`${process.pid}-${Date.now()}-${C(4).toString("hex")}`,n=o(t,`cursor-agent-home-${y}`),s=o(n,".cursor");a(s,{recursive:!0});let i=_(),u=o(i,".cursor");if(c(u))for(let e of b){let f=o(u,e);if(c(f))try{m(f,o(s,e))}catch{}}if(process.platform==="darwin"){let e=o(i,"Library");if(c(e))try{S(e,o(n,"Library"))}catch{}}return n}function k(r){if(!(!r||typeof r!="string"))try{let t=o(r,"Library");try{p(t).isSymbolicLink()&&L(t)}catch{}l(r,{recursive:!0,force:!0})}catch{}}export{b as CURSOR_HOME_DOT_FILES,O as createIsolatedCursorAgentHome,k as removeIsolatedCursorAgentHome,B as shouldUseIsolatedCursorMcpHome};
@@ -1,4 +1,4 @@
1
- import{exec as e}from"child_process";import{promisify as a}from"util";import{existsSync as i}from"fs";import{join as t}from"path";import{homedir as o}from"os";var n=a(e);async function u(){try{return await n("cursor-agent --version"),"cursor-agent"}catch{let c=[t(o(),".local","bin","cursor-agent"),t(o(),".cursor","bin","cursor-agent"),t(o(),".cursor-agent","bin","cursor-agent")];for(let r of c)if(i(r))try{return await n(`"${r}" --version`),r}catch{}return null}}async function b(){return await u()!==null}function y(){return`
1
+ import{exec as e}from"node:child_process";import{promisify as a}from"node:util";import{existsSync as i}from"node:fs";import{join as t}from"node:path";import{homedir as o}from"node:os";var n=a(e);async function u(){try{return await n("cursor-agent --version"),"cursor-agent"}catch{let c=[t(o(),".local","bin","cursor-agent"),t(o(),".cursor","bin","cursor-agent"),t(o(),".cursor-agent","bin","cursor-agent")];for(let r of c)if(i(r))try{return await n(`"${r}" --version`),r}catch{}return null}}async function b(){return await u()!==null}function y(){return`
2
2
  \u274C cursor-agent CLI not found!
3
3
 
4
4
  To use the Cursor agent, install it from:
@@ -1 +1 @@
1
- import{existsSync as a,readdirSync as f,statSync as s,readFileSync as p}from"fs";import{join as r}from"path";var u=/^live-frame.*\.(png|jpe?g)$/i,l=["live-frame.png","live-frame.jpg"];function g(t){return[r(t,"execute_live","frames"),r(t,"frames"),r(t,"execute_live"),t]}function y(t){let e=[];for(let n of g(t)){if(!a(n))continue;for(let m of l){let i=r(n,m);if(a(i))try{e.push({p:i,mtime:s(i).mtimeMs})}catch{}}let c;try{c=f(n)}catch{continue}for(let m of c){if(!u.test(m))continue;let i=r(n,m);try{let o=s(i);o.isFile()&&e.push({p:i,mtime:o.mtimeMs})}catch{}}}return e.length===0?null:(e.sort((n,c)=>c.mtime-n.mtime),e[0])}function v(t){let e=y(t);if(!e)return null;try{return{base64:p(e.p).toString("base64"),mime:e.p.toLowerCase().endsWith(".png")?"image/png":"image/jpeg",mtime:e.mtime,path:e.p}}catch{return null}}export{y as findLatestLiveFrameFileSync,g as liveFrameScanDirs,v as readLatestLiveFramePayloadSync};
1
+ import{existsSync as a,readdirSync as f,statSync as s,readFileSync as p}from"node:fs";import{join as r}from"node:path";var u=/^live-frame.*\.(png|jpe?g)$/i,l=["live-frame.png","live-frame.jpg"];function g(t){return[r(t,"execute_live","frames"),r(t,"frames"),r(t,"execute_live"),t]}function y(t){let e=[];for(let n of g(t)){if(!a(n))continue;for(let m of l){let i=r(n,m);if(a(i))try{e.push({p:i,mtime:s(i).mtimeMs})}catch{}}let c;try{c=f(n)}catch{continue}for(let m of c){if(!u.test(m))continue;let i=r(n,m);try{let o=s(i);o.isFile()&&e.push({p:i,mtime:o.mtimeMs})}catch{}}}return e.length===0?null:(e.sort((n,c)=>c.mtime-n.mtime),e[0])}function v(t){let e=y(t);if(!e)return null;try{return{base64:p(e.p).toString("base64"),mime:e.p.toLowerCase().endsWith(".png")?"image/png":"image/jpeg",mtime:e.mtime,path:e.p}}catch{return null}}export{y as findLatestLiveFrameFileSync,g as liveFrameScanDirs,v as readLatestLiveFramePayloadSync};
@@ -1,4 +1,4 @@
1
- import{readFileSync as S,writeFileSync as y,existsSync as u,mkdirSync as k}from"fs";import{join as d}from"path";import{homedir as v}from"os";var C=new Map;function a(e){return C.get(e)||null}var f=d(v(),".cursor","mcp.json");function h(e){let r=new Set;if(!e||typeof e!="object")return r;for(let o of Object.keys(e)){let t=e[o];if(Array.isArray(t.tools))for(let s of t.tools)r.add(s)}return r}function x(e){let r=h(e);if(r.size===0)return console.log("[MCP Config] No tools requested \u2014 skipping MCP config write"),!1;let o={mcpServers:{}};try{u(f)&&(o=JSON.parse(S(f,"utf-8")),o.mcpServers||(o.mcpServers={}))}catch(i){console.warn(`[MCP Config] Could not read existing config, starting fresh: ${i.message}`),o={mcpServers:{}}}let t=0;for(let i of r){let n=a(i);if(!n){console.log(`[MCP Config] Unknown skill "${i}" \u2014 skipping`);continue}if(o.mcpServers[n.serverName]){console.log(`[MCP Config] Server "${n.serverName}" already configured \u2014 skipping`);continue}let g={},p=!1;for(let c of n.envKeys||[]){let m=process.env[c];if(!m){console.warn(`[MCP Config] Missing env var ${c} for skill "${i}" \u2014 skipping server`),p=!0;break}g[c]=m}if(p)continue;let l=(n.args||[]).map(c=>c);if(n.command==="node"&&l.length>0&&!u(l[0])){console.warn(`[MCP Config] Binary not found at ${l[0]} for "${i}" \u2014 skipping server`);continue}o.mcpServers[n.serverName]={command:n.command,args:l,env:g,description:n.description},t++,console.log(`[MCP Config] Added "${n.serverName}" server`)}if(t===0)return console.log("[MCP Config] No new MCP servers to add"),!1;let s=d(v(),".cursor");return u(s)||k(s,{recursive:!0}),y(f,JSON.stringify(o,null,2),"utf-8"),console.log(`[MCP Config] Wrote ${f} with ${Object.keys(o.mcpServers).length} server(s)`),!0}function N(e){if(!Array.isArray(e)||e.length===0)return"";let r=[];for(let o of e){let t=a(o);if(!t)continue;let s=(t.tools||[]).map(i=>`- ${i.name}: ${i.description}`).join(`
1
+ import{readFileSync as S,writeFileSync as y,existsSync as u,mkdirSync as k}from"node:fs";import{join as d}from"node:path";import{homedir as v}from"node:os";var C=new Map;function a(e){return C.get(e)||null}var f=d(v(),".cursor","mcp.json");function h(e){let r=new Set;if(!e||typeof e!="object")return r;for(let o of Object.keys(e)){let t=e[o];if(Array.isArray(t.tools))for(let s of t.tools)r.add(s)}return r}function x(e){let r=h(e);if(r.size===0)return console.log("[MCP Config] No tools requested \u2014 skipping MCP config write"),!1;let o={mcpServers:{}};try{u(f)&&(o=JSON.parse(S(f,"utf-8")),o.mcpServers||(o.mcpServers={}))}catch(i){console.warn(`[MCP Config] Could not read existing config, starting fresh: ${i.message}`),o={mcpServers:{}}}let t=0;for(let i of r){let n=a(i);if(!n){console.log(`[MCP Config] Unknown skill "${i}" \u2014 skipping`);continue}if(o.mcpServers[n.serverName]){console.log(`[MCP Config] Server "${n.serverName}" already configured \u2014 skipping`);continue}let g={},p=!1;for(let c of n.envKeys||[]){let m=process.env[c];if(!m){console.warn(`[MCP Config] Missing env var ${c} for skill "${i}" \u2014 skipping server`),p=!0;break}g[c]=m}if(p)continue;let l=(n.args||[]).map(c=>c);if(n.command==="node"&&l.length>0&&!u(l[0])){console.warn(`[MCP Config] Binary not found at ${l[0]} for "${i}" \u2014 skipping server`);continue}o.mcpServers[n.serverName]={command:n.command,args:l,env:g,description:n.description},t++,console.log(`[MCP Config] Added "${n.serverName}" server`)}if(t===0)return console.log("[MCP Config] No new MCP servers to add"),!1;let s=d(v(),".cursor");return u(s)||k(s,{recursive:!0}),y(f,JSON.stringify(o,null,2),"utf-8"),console.log(`[MCP Config] Wrote ${f} with ${Object.keys(o.mcpServers).length} server(s)`),!0}function N(e){if(!Array.isArray(e)||e.length===0)return"";let r=[];for(let o of e){let t=a(o);if(!t)continue;let s=(t.tools||[]).map(i=>`- ${i.name}: ${i.description}`).join(`
2
2
  `);r.push(`### ${t.description}
3
3
  ${s}`)}return r.length===0?"":`
4
4
 
@@ -1,2 +1,2 @@
1
- import{readFileSync as K,writeFileSync as k,existsSync as U}from"fs";import{join as _}from"path";var S=class{constructor(t={}){this.config=t,this.enabled=t.enabled!==!1,this.priority=t.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(t){return this.enabled}async enrich(t,n){throw new Error("EventEnricher.enrich() must be implemented")}handleError(t,n){return console.warn(`[${this.getName()}] Enrichment failed for event ${n.type}:`,t.message),null}};import{readFileSync as W,existsSync as O,readdirSync as C}from"fs";import{join as P}from"path";import{execSync as I}from"child_process";import{tmpdir as Z}from"os";var E=class{static async parseTraceZip(t){let n;if(t.endsWith(".zip")&&O(t)){let r=P(Z(),`trace-${Date.now()}`);I(`unzip -q "${t}" -d "${r}"`,{stdio:"pipe"});let e=C(r).find(i=>i.endsWith(".trace"));if(!e)throw new Error("No .trace file found in zip");n=P(r,e)}else if(O(t)){let o=C(t).find(e=>e.endsWith(".trace"));if(!o)throw new Error("No .trace file found");n=P(t,o)}else throw new Error(`Trace not found at ${t}`);try{let o=W(n,"utf-8").trim().split(`
2
- `),e=[],i=new Map,l=new Map;for(let p of o)try{let s=JSON.parse(p);if(s.type==="snapshot"&&s.snapshot&&s.snapshot.accessibility){let u=new Map;for(let h of s.snapshot.accessibility)h.ref&&u.set(h.ref,h);i.set(s.snapshotName,u)}if(s.type==="frame-snapshot"&&s.snapshot){let u=Buffer.from(s.snapshot.html||"","base64").toString("utf-8");u&&u.length>100&&l.set(s.pageId||"default",u)}}catch{}for(let p of o)try{let s=JSON.parse(p);if(s.type==="before"&&s.params&&s.params.selector){let u=s.method;if(["click","fill","type","selectOption"].includes(u)){let h=s.params.selector,N=s.params.text||s.params.value||"",a=[],f=null,m=null,d=null,F=h.match(/aria-ref=([a-z0-9]+)/i);if(F&&s.snapshotName){let c=F[1],y=i.get(s.snapshotName);if(y&&y.has(c)){let g=y.get(c);f=g.name||null,m=g.role||null,d=g.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${f}", role="${m}"`)}}let x=h.match(/internal:text="([^"]+)"/i),R=h.match(/internal:label="([^"]+)"/i),A=h.match(/internal:placeholder="([^"]+)"/i),j=h.match(/internal:role=([^ ]+)/i),T=h.match(/internal:describe="([^"]+)"/i),D=h.match(/name="([^"]+)"/i);if(x){a.push({type:"text",text:x[1]});let c=x[1].split(" ");c.length>1&&(a.push({type:"text",text:c[0],fuzzy:!0}),a.push({type:"text",text:c[c.length-1],fuzzy:!0}))}if(R&&a.push({type:"label",label:R[1]}),A&&a.push({type:"placeholder",placeholder:A[1]}),f){a.unshift({type:"text",text:f,source:"accessibility-tree"});let c=f.split(" ");c.length>1&&a.push({type:"text",text:c[0],fuzzy:!0,source:"accessibility-tree"})}if(m||j){let c=m||j[1],y=f||(D?D[1]:x?x[1]:null);a.unshift({type:"role",role:c,name:y,source:f?"accessibility-tree":"selector"})}if(d&&a.unshift({type:"label",label:d,source:"accessibility-tree"}),T){let c=T[1],y=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],g=null,v=c;for(let b of y)if(c.toLowerCase().endsWith(` ${b}`)){g=b.replace(" ",""),v=c.substring(0,c.length-b.length-1);break}if(g){a.push({type:"role",role:g,name:v});let b=v.replace(/\s*\([^)]+\)\s*$/,"");a.push({type:"text",text:b}),a.push({type:"text",text:v});let z=v.split(" ");z.length>1&&(a.push({type:"text",text:z[0],fuzzy:!0}),a.push({type:"text",text:z.slice(0,2).join(" "),fuzzy:!0}))}else{let b=c.replace(/\s*\([^)]+\)\s*$/,"");a.push({type:"text",text:b}),a.push({type:"text",text:c})}}let B=this.extractDOMStrategies(h,l,x?.[1]||T?.[1],s.pageId);a.push(...B);let $=this.extractStructuralContext(h);($.parent||$.sibling)&&a.forEach(c=>{["role","text","label","testid"].includes(c.type)&&($.parent&&(c.parent=$.parent),$.sibling&&(c.sibling=$.sibling))}),a.push({type:"css",value:h});let J=f||x?x[1]:T?T[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${e.length}`;e.push({method:u,name:J,action:u==="type"?"fill":u,value:N,strategies:a,timestamp:s.startTime,actualText:f,actualRole:m,actualAriaLabel:d})}}}catch{}return e}catch(r){throw new Error(`Failed to parse trace: ${r.message}`,{cause:r})}}static extractDOMStrategies(t,n,r,o){let e=[];if(!n||n.size===0||!r)return e;try{let i=n.get(o);if(!i)return e;let l=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),p=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),s=i.match(p);s&&e.push({type:"testid",value:s[1],priority:"high"});let u=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${l}`,"gi"),h=i.matchAll(u);for(let f of h){let m=f[1].split(/\s+/).filter(d=>d&&!d.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&d.length>2);m.length>0&&(e.push({type:"class",value:m.join("."),priority:"medium"}),m.length===1&&e.push({type:"class",value:m[0],priority:"medium"}))}let N=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),a=i.match(N);a&&!a[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&e.push({type:"id",value:a[1],priority:"high"})}catch(i){console.warn(`[TraceParser] DOM extraction failed: ${i.message}`)}return e}static extractStructuralContext(t){let n={parent:null,sibling:null},r=t.split(">>").map(i=>i.trim());if(r.length>1){let l=r[r.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();l&&(l.match(/^(form|section|nav|header|aside|main|article)\b/)||l.includes("[")||l.match(/[#.]\w/))&&(n.parent=l)}let e=r[r.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return e&&(n.sibling=e[1].trim()),n}};import{existsSync as q}from"fs";import{join as L}from"path";var M=class extends S{constructor(t={}){super(t),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(t){if(this.traceData)return;let n=L(t,"traces"),r=L(t,"trace.zip");if(q(r))try{this.traceData=await E.parseTraceZip(r),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(o){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${o.message}`)}}async enrich(t,n){let r=t.data?.params?.ref,o=t.id;if(r===void 0&&o===void 0||(!this.traceData&&n.sessionPath&&await this.loadTrace(n.sessionPath),!this.traceData))return null;let e=this.traceData[o];if(!e)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${o}`),null;let i=e.actualText||this._extractTextFromSelector(e.selector),l=e.actualRole,p=e.actualAriaLabel;return i||l||p?(console.log(`[TraceTextEnricher] \u2705 Event ${o}: text="${i}", role="${l}", label="${p}"`),{traceActualText:i,traceActualRole:l,traceActualAriaLabel:p,traceSelector:e.selector,traceStrategies:e.strategies}):null}_extractTextFromSelector(t){if(!t)return null;let n=t.match(/internal:label="([^"]+)"/);if(n)return n[1];let r=t.match(/internal:text="([^"]+)"/);if(r)return r[1];let o=t.match(/getByText\(['"]([^'"]+)['"]\)/);if(o)return o[1];let e=t.match(/name:\s*['"]([^'"]+)['"]/);return e?e[1]:null}};async function ot(w){let t=_(w,"events.json"),n=_(w,"events-enriched.json");if(!U(t))return console.log("[PostProcess] No events.json found"),{enriched:0,failed:0};try{let r=JSON.parse(K(t,"utf-8")),o=new M,e=0,i=0;for(let l of r)try{let p=await o.enrich(l,{sessionPath:w});p&&(l.enrichedData={...l.enrichedData||{},...p},e++)}catch(p){console.log(`[PostProcess] Failed to enrich event ${l.id}: ${p.message}`),i++}return e>0&&(k(n,JSON.stringify(r,null,2)),k(t,JSON.stringify(r,null,2)),console.log(`[PostProcess] \u2705 Enriched ${e} events (${i} failed)`)),{enriched:e,failed:i}}catch(r){return console.log(`[PostProcess] \u274C Failed to post-process events: ${r.message}`),{enriched:0,failed:0}}}export{ot as postProcessEvents};
1
+ import{readFileSync as K,writeFileSync as k,existsSync as U}from"node:fs";import{join as _}from"node:path";var S=class{constructor(t={}){this.config=t,this.enabled=t.enabled!==!1,this.priority=t.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(t){return this.enabled}async enrich(t,n){throw new Error("EventEnricher.enrich() must be implemented")}handleError(t,n){return console.warn(`[${this.getName()}] Enrichment failed for event ${n.type}:`,t.message),null}};import{readFileSync as W,existsSync as O,readdirSync as C}from"node:fs";import{join as P}from"node:path";import{execSync as I}from"node:child_process";import{tmpdir as Z}from"node:os";var E=class{static async parseTraceZip(t){let n;if(t.endsWith(".zip")&&O(t)){let r=P(Z(),`trace-${Date.now()}`);I(`unzip -q "${t}" -d "${r}"`,{stdio:"pipe"});let e=C(r).find(i=>i.endsWith(".trace"));if(!e)throw new Error("No .trace file found in zip");n=P(r,e)}else if(O(t)){let o=C(t).find(e=>e.endsWith(".trace"));if(!o)throw new Error("No .trace file found");n=P(t,o)}else throw new Error(`Trace not found at ${t}`);try{let o=W(n,"utf-8").trim().split(`
2
+ `),e=[],i=new Map,l=new Map;for(let p of o)try{let s=JSON.parse(p);if(s.type==="snapshot"&&s.snapshot&&s.snapshot.accessibility){let u=new Map;for(let h of s.snapshot.accessibility)h.ref&&u.set(h.ref,h);i.set(s.snapshotName,u)}if(s.type==="frame-snapshot"&&s.snapshot){let u=Buffer.from(s.snapshot.html||"","base64").toString("utf-8");u&&u.length>100&&l.set(s.pageId||"default",u)}}catch{}for(let p of o)try{let s=JSON.parse(p);if(s.type==="before"&&s.params&&s.params.selector){let u=s.method;if(["click","fill","type","selectOption"].includes(u)){let h=s.params.selector,N=s.params.text||s.params.value||"",a=[],f=null,m=null,d=null,F=h.match(/aria-ref=([a-z0-9]+)/i);if(F&&s.snapshotName){let c=F[1],y=i.get(s.snapshotName);if(y&&y.has(c)){let g=y.get(c);f=g.name||null,m=g.role||null,d=g.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${f}", role="${m}"`)}}let x=h.match(/internal:text="([^"]+)"/i),R=h.match(/internal:label="([^"]+)"/i),A=h.match(/internal:placeholder="([^"]+)"/i),j=h.match(/internal:role=([^ ]+)/i),T=h.match(/internal:describe="([^"]+)"/i),D=h.match(/name="([^"]+)"/i);if(x){a.push({type:"text",text:x[1]});let c=x[1].split(" ");c.length>1&&(a.push({type:"text",text:c[0],fuzzy:!0}),a.push({type:"text",text:c[c.length-1],fuzzy:!0}))}if(R&&a.push({type:"label",label:R[1]}),A&&a.push({type:"placeholder",placeholder:A[1]}),f){a.unshift({type:"text",text:f,source:"accessibility-tree"});let c=f.split(" ");c.length>1&&a.push({type:"text",text:c[0],fuzzy:!0,source:"accessibility-tree"})}if(m||j){let c=m||j[1],y=f||(D?D[1]:x?x[1]:null);a.unshift({type:"role",role:c,name:y,source:f?"accessibility-tree":"selector"})}if(d&&a.unshift({type:"label",label:d,source:"accessibility-tree"}),T){let c=T[1],y=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],g=null,v=c;for(let b of y)if(c.toLowerCase().endsWith(` ${b}`)){g=b.replace(" ",""),v=c.substring(0,c.length-b.length-1);break}if(g){a.push({type:"role",role:g,name:v});let b=v.replace(/\s*\([^)]+\)\s*$/,"");a.push({type:"text",text:b}),a.push({type:"text",text:v});let z=v.split(" ");z.length>1&&(a.push({type:"text",text:z[0],fuzzy:!0}),a.push({type:"text",text:z.slice(0,2).join(" "),fuzzy:!0}))}else{let b=c.replace(/\s*\([^)]+\)\s*$/,"");a.push({type:"text",text:b}),a.push({type:"text",text:c})}}let B=this.extractDOMStrategies(h,l,x?.[1]||T?.[1],s.pageId);a.push(...B);let $=this.extractStructuralContext(h);($.parent||$.sibling)&&a.forEach(c=>{["role","text","label","testid"].includes(c.type)&&($.parent&&(c.parent=$.parent),$.sibling&&(c.sibling=$.sibling))}),a.push({type:"css",value:h});let J=f||x?x[1]:T?T[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${e.length}`;e.push({method:u,name:J,action:u==="type"?"fill":u,value:N,strategies:a,timestamp:s.startTime,actualText:f,actualRole:m,actualAriaLabel:d})}}}catch{}return e}catch(r){throw new Error(`Failed to parse trace: ${r.message}`,{cause:r})}}static extractDOMStrategies(t,n,r,o){let e=[];if(!n||n.size===0||!r)return e;try{let i=n.get(o);if(!i)return e;let l=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),p=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),s=i.match(p);s&&e.push({type:"testid",value:s[1],priority:"high"});let u=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${l}`,"gi"),h=i.matchAll(u);for(let f of h){let m=f[1].split(/\s+/).filter(d=>d&&!d.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&d.length>2);m.length>0&&(e.push({type:"class",value:m.join("."),priority:"medium"}),m.length===1&&e.push({type:"class",value:m[0],priority:"medium"}))}let N=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),a=i.match(N);a&&!a[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&e.push({type:"id",value:a[1],priority:"high"})}catch(i){console.warn(`[TraceParser] DOM extraction failed: ${i.message}`)}return e}static extractStructuralContext(t){let n={parent:null,sibling:null},r=t.split(">>").map(i=>i.trim());if(r.length>1){let l=r[r.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();l&&(l.match(/^(form|section|nav|header|aside|main|article)\b/)||l.includes("[")||l.match(/[#.]\w/))&&(n.parent=l)}let e=r[r.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return e&&(n.sibling=e[1].trim()),n}};import{existsSync as q}from"node:fs";import{join as L}from"node:path";var M=class extends S{constructor(t={}){super(t),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(t){if(this.traceData)return;let n=L(t,"traces"),r=L(t,"trace.zip");if(q(r))try{this.traceData=await E.parseTraceZip(r),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(o){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${o.message}`)}}async enrich(t,n){let r=t.data?.params?.ref,o=t.id;if(r===void 0&&o===void 0||(!this.traceData&&n.sessionPath&&await this.loadTrace(n.sessionPath),!this.traceData))return null;let e=this.traceData[o];if(!e)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${o}`),null;let i=e.actualText||this._extractTextFromSelector(e.selector),l=e.actualRole,p=e.actualAriaLabel;return i||l||p?(console.log(`[TraceTextEnricher] \u2705 Event ${o}: text="${i}", role="${l}", label="${p}"`),{traceActualText:i,traceActualRole:l,traceActualAriaLabel:p,traceSelector:e.selector,traceStrategies:e.strategies}):null}_extractTextFromSelector(t){if(!t)return null;let n=t.match(/internal:label="([^"]+)"/);if(n)return n[1];let r=t.match(/internal:text="([^"]+)"/);if(r)return r[1];let o=t.match(/getByText\(['"]([^'"]+)['"]\)/);if(o)return o[1];let e=t.match(/name:\s*['"]([^'"]+)['"]/);return e?e[1]:null}};async function ot(w){let t=_(w,"events.json"),n=_(w,"events-enriched.json");if(!U(t))return console.log("[PostProcess] No events.json found"),{enriched:0,failed:0};try{let r=JSON.parse(K(t,"utf-8")),o=new M,e=0,i=0;for(let l of r)try{let p=await o.enrich(l,{sessionPath:w});p&&(l.enrichedData={...l.enrichedData||{},...p},e++)}catch(p){console.log(`[PostProcess] Failed to enrich event ${l.id}: ${p.message}`),i++}return e>0&&(k(n,JSON.stringify(r,null,2)),k(t,JSON.stringify(r,null,2)),console.log(`[PostProcess] \u2705 Enriched ${e} events (${i} failed)`)),{enriched:e,failed:i}}catch(r){return console.log(`[PostProcess] \u274C Failed to post-process events: ${r.message}`),{enriched:0,failed:0}}}export{ot as postProcessEvents};
@@ -1 +1 @@
1
- import{execSync as w}from"child_process";import{existsSync as E,mkdirSync as b}from"fs";import{join as R}from"path";async function S(g={}){let{baseDir:c="/workspace/repos",repos:p=null,depth:m=1,branch:u=null}=g,h=process.env.REPOS;if(!h)throw new Error("REPOS environment variable not set. Are you running in a Zibby workflow container?");let r;try{r=JSON.parse(h)}catch(e){throw new Error(`Failed to parse REPOS env var: ${e.message}`,{cause:e})}if(!Array.isArray(r)||r.length===0)throw new Error("No repositories configured for this project");let f=p?r.filter(e=>p.includes(e.name)):r;if(f.length===0)throw new Error(`No matching repositories found. Available: ${r.map(e=>e.name).join(", ")}`);E(c)||b(c,{recursive:!0});let n={};return await Promise.all(f.map(async e=>{let o=e.provider||"github",t=o==="gitlab"?process.env.GITLAB_TOKEN:process.env.GITHUB_TOKEN;if(!t){console.error(`${o.toUpperCase()}_TOKEN not set, skipping ${e.name}`),n[e.name]=null;return}let d=e.name.replace(/\//g,"-"),l=R(c,d),s=e.cloneUrl||e.url;if(!s){console.error(`Repository "${e.name}" has no clone URL`),n[e.name]=null;return}let i;o==="gitlab"?i=s.replace(/^https:\/\//,`https://oauth2:${t}@`):i=s.replace(/^https:\/\//,`https://x-access-token:${t}@`);let a=["clone"];m>0&&a.push("--depth",m.toString()),u&&a.push("--branch",u),a.push(i,l);let y=`git ${a.join(" ")}`;console.log(`Cloning ${e.name} (${o}) to ${l}...`);try{w(y,{stdio:"pipe",env:{...process.env,GIT_TERMINAL_PROMPT:"0"}}),console.log(`Repository ${e.name} cloned successfully`),n[e.name]=l}catch($){let v=$.message.replace(t,"***").replace(i,s);console.error(`Failed to clone ${e.name}: ${v}`),n[e.name]=null}})),n}export{S as cloneRepo};
1
+ import{execSync as w}from"node:child_process";import{existsSync as E,mkdirSync as b}from"node:fs";import{join as R}from"node:path";async function S(g={}){let{baseDir:c="/workspace/repos",repos:p=null,depth:m=1,branch:u=null}=g,h=process.env.REPOS;if(!h)throw new Error("REPOS environment variable not set. Are you running in a Zibby workflow container?");let r;try{r=JSON.parse(h)}catch(e){throw new Error(`Failed to parse REPOS env var: ${e.message}`,{cause:e})}if(!Array.isArray(r)||r.length===0)throw new Error("No repositories configured for this project");let f=p?r.filter(e=>p.includes(e.name)):r;if(f.length===0)throw new Error(`No matching repositories found. Available: ${r.map(e=>e.name).join(", ")}`);E(c)||b(c,{recursive:!0});let n={};return await Promise.all(f.map(async e=>{let o=e.provider||"github",t=o==="gitlab"?process.env.GITLAB_TOKEN:process.env.GITHUB_TOKEN;if(!t){console.error(`${o.toUpperCase()}_TOKEN not set, skipping ${e.name}`),n[e.name]=null;return}let d=e.name.replace(/\//g,"-"),l=R(c,d),s=e.cloneUrl||e.url;if(!s){console.error(`Repository "${e.name}" has no clone URL`),n[e.name]=null;return}let i;o==="gitlab"?i=s.replace(/^https:\/\//,`https://oauth2:${t}@`):i=s.replace(/^https:\/\//,`https://x-access-token:${t}@`);let a=["clone"];m>0&&a.push("--depth",m.toString()),u&&a.push("--branch",u),a.push(i,l);let y=`git ${a.join(" ")}`;console.log(`Cloning ${e.name} (${o}) to ${l}...`);try{w(y,{stdio:"pipe",env:{...process.env,GIT_TERMINAL_PROMPT:"0"}}),console.log(`Repository ${e.name} cloned successfully`),n[e.name]=l}catch($){let v=$.message.replace(t,"***").replace(i,s);console.error(`Failed to clone ${e.name}: ${v}`),n[e.name]=null}})),n}export{S as cloneRepo};
@@ -1 +1 @@
1
- import{writeFileSync as g,existsSync as _,mkdirSync as m}from"fs";import{join as d}from"path";import f from"chalk";var r={debug:0,info:1,warn:2,error:3,silent:4},u=class{constructor(){this._level=this._getLogLevel()}_getLogLevel(){if(process.env.ZIBBY_DEBUG==="true")return r.debug;if(process.env.ZIBBY_VERBOSE==="true")return r.info;let e=process.env.LOG_LEVEL?.toLowerCase();return e&&e in r?r[e]:r.info}_shouldLog(e){return r[e]>=this._level}_formatMessage(e,t,s={}){let o=new Date().toISOString(),n=`${this._getPrefix(e)} ${t}`;return Object.keys(s).length>0&&(n+=f.dim(` ${JSON.stringify(s)}`)),n}_getPrefix(e){return{debug:f.gray("[DEBUG]"),info:f.cyan("[INFO]"),warn:f.yellow("[WARN]"),error:f.red("\u274C [ERROR]")}[e]||""}debug(e,t){this._shouldLog("debug")&&console.log(this._formatMessage("debug",e,t))}info(e,t){this._shouldLog("info")&&console.log(this._formatMessage("info",e,t))}warn(e,t){this._shouldLog("warn")&&console.warn(this._formatMessage("warn",e,t))}error(e,t){this._shouldLog("error")&&console.error(this._formatMessage("error",e,t))}setLevel(e){e in r&&(this._level=r[e])}getLevel(){return Object.keys(r).find(e=>r[e]===this._level)}},c=new u;var h=class l{static saveTitle(e,t){let s=e.state.sessionPath;if(!s)return;let o=l._findInState(e.state,"title")||l._findInState(e.state,"result");if(!(!o||typeof o!="string"))try{let a=d(s,"title.txt");g(a,o,"utf-8"),c.info(`Saved title to session: "${o}"`)}catch(a){console.warn("\u26A0\uFE0F Could not save title file:",a.message)}}static _findInState(e,t){for(let[,s]of Object.entries(e))if(s&&typeof s=="object"&&s[t]!==void 0)return s[t]}static async saveExecutionData(e){let t=e.state.sessionPath;if(t)for(let[s,o]of Object.entries(e.state)){if(!o||typeof o!="object")continue;let a=Array.isArray(o.actions)&&o.actions.length>0,n=typeof o.scriptPath=="string"&&o.scriptPath.trim().length>0;if(!(!a&&!n))try{let i=d(t,s);_(i)||m(i,{recursive:!0});let p=d(i,"result.json");g(p,JSON.stringify(o,null,2),"utf-8"),c.info(`Saved execution data to ${s} folder`),await this.onNodeSaved(i,o)}catch(i){console.warn(`\u26A0\uFE0F Could not save execution data for ${s}:`,i.message)}}}static async onNodeSaved(e,t){}static logResult(e,t){let s=Object.entries(e.state).filter(([,n])=>n&&typeof n=="object"&&n.success!==void 0),o=s.length>0&&s.every(([,n])=>n.success),a=s.some(([,n])=>n.success===!1);if(o)c.info("Workflow completed successfully."),t&&c.info(`Output: ${t}`);else if(a){let n=s.filter(([,i])=>!i.success).map(([i])=>i);c.info(`Workflow completed with failures in: ${n.join(", ")}`),t&&c.info(`Output: ${t}`)}return o}static handle(e,t,s){return this.saveTitle(e,t),this.saveExecutionData(e),this.logResult(e,s)}};export{h as ResultHandler};
1
+ import{writeFileSync as g,existsSync as _,mkdirSync as m}from"node:fs";import{join as d}from"node:path";import f from"chalk";var r={debug:0,info:1,warn:2,error:3,silent:4},u=class{constructor(){this._level=this._getLogLevel()}_getLogLevel(){if(process.env.ZIBBY_DEBUG==="true")return r.debug;if(process.env.ZIBBY_VERBOSE==="true")return r.info;let e=process.env.LOG_LEVEL?.toLowerCase();return e&&e in r?r[e]:r.info}_shouldLog(e){return r[e]>=this._level}_formatMessage(e,t,s={}){let o=new Date().toISOString(),n=`${this._getPrefix(e)} ${t}`;return Object.keys(s).length>0&&(n+=f.dim(` ${JSON.stringify(s)}`)),n}_getPrefix(e){return{debug:f.gray("[DEBUG]"),info:f.cyan("[INFO]"),warn:f.yellow("[WARN]"),error:f.red("\u274C [ERROR]")}[e]||""}debug(e,t){this._shouldLog("debug")&&console.log(this._formatMessage("debug",e,t))}info(e,t){this._shouldLog("info")&&console.log(this._formatMessage("info",e,t))}warn(e,t){this._shouldLog("warn")&&console.warn(this._formatMessage("warn",e,t))}error(e,t){this._shouldLog("error")&&console.error(this._formatMessage("error",e,t))}setLevel(e){e in r&&(this._level=r[e])}getLevel(){return Object.keys(r).find(e=>r[e]===this._level)}},c=new u;var h=class l{static saveTitle(e,t){let s=e.state.sessionPath;if(!s)return;let o=l._findInState(e.state,"title")||l._findInState(e.state,"result");if(!(!o||typeof o!="string"))try{let a=d(s,"title.txt");g(a,o,"utf-8"),c.info(`Saved title to session: "${o}"`)}catch(a){console.warn("\u26A0\uFE0F Could not save title file:",a.message)}}static _findInState(e,t){for(let[,s]of Object.entries(e))if(s&&typeof s=="object"&&s[t]!==void 0)return s[t]}static async saveExecutionData(e){let t=e.state.sessionPath;if(t)for(let[s,o]of Object.entries(e.state)){if(!o||typeof o!="object")continue;let a=Array.isArray(o.actions)&&o.actions.length>0,n=typeof o.scriptPath=="string"&&o.scriptPath.trim().length>0;if(!(!a&&!n))try{let i=d(t,s);_(i)||m(i,{recursive:!0});let p=d(i,"result.json");g(p,JSON.stringify(o,null,2),"utf-8"),c.info(`Saved execution data to ${s} folder`),await this.onNodeSaved(i,o)}catch(i){console.warn(`\u26A0\uFE0F Could not save execution data for ${s}:`,i.message)}}}static async onNodeSaved(e,t){}static logResult(e,t){let s=Object.entries(e.state).filter(([,n])=>n&&typeof n=="object"&&n.success!==void 0),o=s.length>0&&s.every(([,n])=>n.success),a=s.some(([,n])=>n.success===!1);if(o)c.info("Workflow completed successfully."),t&&c.info(`Output: ${t}`);else if(a){let n=s.filter(([,i])=>!i.success).map(([i])=>i);c.info(`Workflow completed with failures in: ${n.join(", ")}`),t&&c.info(`Output: ${t}`)}return o}static handle(e,t,s){return this.saveTitle(e,t),this.saveExecutionData(e),this.logResult(e,s)}};export{h as ResultHandler};
@@ -1,3 +1,3 @@
1
- import{existsSync as et,mkdirSync as N,readFileSync as nt,rmSync as rt,statSync as ot,writeFileSync as it}from"fs";import{join as m}from"path";import{randomUUID as ut}from"crypto";var U=".zibby/output",O="sessions";function M(t){if(!t||typeof t!="object")return 8;let e=t.parallel;if(!e||typeof e!="object")return 8;let r=e.maxConcurrentRuns??e.maxConcurrent,n=Number(r);if(!Number.isFinite(n))return 8;let o=Math.floor(n);return o<1?8:Math.min(64,o)}function h(t){if(!t||typeof t!="object")return!1;let e=t.parallel;return!(!e||typeof e!="object"||e.waitWhenAtCapacity===!1)}import{existsSync as E,mkdirSync as X,readFileSync as k,readdirSync as L,statSync as F,writeFileSync as Q}from"fs";import{join as C}from"path";function S(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(r){let n=r&&typeof r=="object"?r.code:"";return n==="ESRCH"?!1:n==="EPERM"?!0:null}}function H(t,e={}){if(!t||!E(t))return{patched:0};let r=e.studioNoPidMaxAgeMs!=null&&Number.isFinite(e.studioNoPidMaxAgeMs)?Math.max(0,e.studioNoPidMaxAgeMs):120*1e3,n=Date.now(),o=0,i;try{i=L(t)}catch{return{patched:0}}for(let s of i){let u=C(t,s),a;try{a=F(u)}catch{continue}if(!a.isDirectory())continue;let c=x(u);if(!c||c.status!=="running")continue;let l=Number(c.updatedAt)||0,y=S(c.pid),f=!1,p="";y===!1?(f=!0,p="process-exited"):y===null&&c.runSource==="studio"&&r>0&&l>0&&n-l>r&&(f=!0,p="studio-stale-no-pid"),f&&(K(u,{status:"interrupted",activeNode:null,activeStageIndex:null,exitReason:p}),o+=1)}return{patched:o}}var $="zibby-run-state.json";function g(t){return C(t,$)}function x(t){if(!t||typeof t!="string")return null;let e=g(t);if(!E(e))return null;try{let r=k(e,"utf8"),n=JSON.parse(r);return n&&typeof n=="object"?n:null}catch{return null}}function K(t,e){if(!t||typeof t!="string")return;try{X(t,{recursive:!0})}catch{return}let n={...x(t)||{v:1},...e,v:1,updatedAt:Date.now()};try{Q(g(t),`${JSON.stringify(n)}
2
- `,"utf8")}catch(o){console.warn(`[zibby run-state] ${o.message}`)}}function v(t,e={}){if(!t||!E(t))return[];e.reconcile!==!1&&H(t,e.reconcile||{});let r=e.maxStaleMs!=null&&Number.isFinite(e.maxStaleMs)&&e.maxStaleMs>0?e.maxStaleMs:1800*1e3,n=typeof e.now=="number"?e.now:Date.now(),o;try{o=L(t)}catch{return[]}let i=[];for(let s of o){let u=C(t,s),a;try{a=F(u)}catch{continue}if(!a.isDirectory())continue;let c=x(u);if(!c||c.status!=="running")continue;let l=Number(c.updatedAt)||0;r>0&&l>0&&n-l>r||i.push({sessionId:s,sessionPathAbs:u,...c})}return i}import{existsSync as A,mkdirSync as Y,readFileSync as J,renameSync as q,unlinkSync as z,writeFileSync as V}from"fs";import{join as G}from"path";var Z="run-capacity-wait.json",d=1,tt=10800*1e3;function b(t){return G(t,Z)}function _(){return{v:d,entries:[]}}function D(t){if(!t||!A(t))return _();let e=b(t);if(!A(e))return _();try{let r=J(e,"utf8"),n=JSON.parse(r);if(!n||typeof n!="object")return _();let o=Array.isArray(n.entries)?n.entries:[];return{v:d,entries:o}}catch{return _()}}function j(t,e=Date.now()){let r=t&&Array.isArray(t.entries)?t.entries:[],n=[];for(let o of r){if(!o||typeof o!="object")continue;let i=Number(o.pid),s=Number(o.updatedAt)||Number(o.enqueuedAt)||0,u=Number.isFinite(i)&&i>0?S(i):null;u!==!1&&(u===null&&s>0&&e-s>tt||n.push(o))}return{v:d,entries:n}}function P(t,e){let r=b(t);Y(t,{recursive:!0});let n={v:d,entries:Array.isArray(e.entries)?e.entries:[]},o=`${r}.${process.pid}.${Date.now()}.tmp`;V(o,`${JSON.stringify(n)}
1
+ import{existsSync as et,mkdirSync as N,readFileSync as nt,rmSync as rt,statSync as ot,writeFileSync as it}from"node:fs";import{join as m}from"node:path";import{randomUUID as ut}from"node:crypto";var U=".zibby/output",O="sessions";function M(t){if(!t||typeof t!="object")return 8;let e=t.parallel;if(!e||typeof e!="object")return 8;let r=e.maxConcurrentRuns??e.maxConcurrent,n=Number(r);if(!Number.isFinite(n))return 8;let o=Math.floor(n);return o<1?8:Math.min(64,o)}function h(t){if(!t||typeof t!="object")return!1;let e=t.parallel;return!(!e||typeof e!="object"||e.waitWhenAtCapacity===!1)}import{existsSync as E,mkdirSync as X,readFileSync as k,readdirSync as L,statSync as F,writeFileSync as Q}from"node:fs";import{join as C}from"node:path";function S(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(r){let n=r&&typeof r=="object"?r.code:"";return n==="ESRCH"?!1:n==="EPERM"?!0:null}}function H(t,e={}){if(!t||!E(t))return{patched:0};let r=e.studioNoPidMaxAgeMs!=null&&Number.isFinite(e.studioNoPidMaxAgeMs)?Math.max(0,e.studioNoPidMaxAgeMs):120*1e3,n=Date.now(),o=0,i;try{i=L(t)}catch{return{patched:0}}for(let s of i){let u=C(t,s),a;try{a=F(u)}catch{continue}if(!a.isDirectory())continue;let c=x(u);if(!c||c.status!=="running")continue;let l=Number(c.updatedAt)||0,y=S(c.pid),f=!1,p="";y===!1?(f=!0,p="process-exited"):y===null&&c.runSource==="studio"&&r>0&&l>0&&n-l>r&&(f=!0,p="studio-stale-no-pid"),f&&(K(u,{status:"interrupted",activeNode:null,activeStageIndex:null,exitReason:p}),o+=1)}return{patched:o}}var $="zibby-run-state.json";function g(t){return C(t,$)}function x(t){if(!t||typeof t!="string")return null;let e=g(t);if(!E(e))return null;try{let r=k(e,"utf8"),n=JSON.parse(r);return n&&typeof n=="object"?n:null}catch{return null}}function K(t,e){if(!t||typeof t!="string")return;try{X(t,{recursive:!0})}catch{return}let n={...x(t)||{v:1},...e,v:1,updatedAt:Date.now()};try{Q(g(t),`${JSON.stringify(n)}
2
+ `,"utf8")}catch(o){console.warn(`[zibby run-state] ${o.message}`)}}function v(t,e={}){if(!t||!E(t))return[];e.reconcile!==!1&&H(t,e.reconcile||{});let r=e.maxStaleMs!=null&&Number.isFinite(e.maxStaleMs)&&e.maxStaleMs>0?e.maxStaleMs:1800*1e3,n=typeof e.now=="number"?e.now:Date.now(),o;try{o=L(t)}catch{return[]}let i=[];for(let s of o){let u=C(t,s),a;try{a=F(u)}catch{continue}if(!a.isDirectory())continue;let c=x(u);if(!c||c.status!=="running")continue;let l=Number(c.updatedAt)||0;r>0&&l>0&&n-l>r||i.push({sessionId:s,sessionPathAbs:u,...c})}return i}import{existsSync as A,mkdirSync as Y,readFileSync as J,renameSync as q,unlinkSync as z,writeFileSync as V}from"node:fs";import{join as G}from"node:path";var Z="run-capacity-wait.json",d=1,tt=10800*1e3;function b(t){return G(t,Z)}function _(){return{v:d,entries:[]}}function D(t){if(!t||!A(t))return _();let e=b(t);if(!A(e))return _();try{let r=J(e,"utf8"),n=JSON.parse(r);if(!n||typeof n!="object")return _();let o=Array.isArray(n.entries)?n.entries:[];return{v:d,entries:o}}catch{return _()}}function j(t,e=Date.now()){let r=t&&Array.isArray(t.entries)?t.entries:[],n=[];for(let o of r){if(!o||typeof o!="object")continue;let i=Number(o.pid),s=Number(o.updatedAt)||Number(o.enqueuedAt)||0,u=Number.isFinite(i)&&i>0?S(i):null;u!==!1&&(u===null&&s>0&&e-s>tt||n.push(o))}return{v:d,entries:n}}function P(t,e){let r=b(t);Y(t,{recursive:!0});let n={v:d,entries:Array.isArray(e.entries)?e.entries:[]},o=`${r}.${process.pid}.${Date.now()}.tmp`;V(o,`${JSON.stringify(n)}
3
3
  `,"utf8");try{A(r)&&z(r)}catch{}q(o,r)}function W(t,e){let r=j(D(t)),n=e?.id!=null?String(e.id):"";if(!n)return;let o=r.entries.filter(s=>s&&String(s.id)!==n),i=Date.now();o.push({...e,id:n,pid:Number.isFinite(Number(e.pid))?Number(e.pid):process.pid,enqueuedAt:Number(e.enqueuedAt)||i,updatedAt:i}),P(t,{v:d,entries:o})}function I(t,e){let r=e!=null?String(e):"";if(!r||!t)return;let n=j(D(t)),o=n.entries.filter(i=>i&&String(i.id)!==r);o.length!==n.entries.length&&P(t,{v:d,entries:o})}var ct=".zibby-run-capacity-guard",st=12e4;function at(t,e){let r=e?.paths?.output||U,n=m(t,r),o=m(n,O);return{outputAbs:n,sessionsRootAbs:o}}function R(t){try{rt(t,{recursive:!0,force:!0})}catch{}}function lt(t){try{let e=nt(m(t,"owner.pid"),"utf8"),r=Number(String(e).trim());return Number.isFinite(r)&&r>0?r:null}catch{return null}}function ft(t){if(!et(t))return!0;let e=lt(t);if(e!=null){let r=S(e);if(r===!0)return!1;if(r===!1)return R(t),!0}try{let r=ot(t);if(Date.now()-r.mtimeMs>st)return R(t),!0}catch{return R(t),!0}return!1}async function pt(t,e){N(t,{recursive:!0});let r=m(t,ct);for(;;)try{N(r,{recursive:!1}),it(m(r,"owner.pid"),String(process.pid),"utf8");try{return await e()}finally{R(r)}}catch(n){if((n&&typeof n=="object"?n.code:"")!=="EEXIST")throw n;if(ft(r))continue;await new Promise(i=>setTimeout(i,35+Math.random()*45))}}async function Mt(t){let{cwd:e,config:r,meta:n={},log:o,pollMs:i=1500}=t;if(process.env.ZIBBY_WAIT_FOR_RUN_CAPACITY==="0"||process.env.ZIBBY_WAIT_FOR_RUN_CAPACITY==="false")return{waited:!1,jobId:""};if(!h(r))return{waited:!1,jobId:""};let s=M(r),{outputAbs:u,sessionsRootAbs:a}=at(e,r);N(u,{recursive:!0});let c=ut(),l=n.studioTestCaseId!=null&&String(n.studioTestCaseId).trim()!==""?String(n.studioTestCaseId).trim():null,y={id:c,pid:process.pid,cwd:String(e),enqueuedAt:Date.now(),updatedAt:Date.now(),source:n.source!=null?String(n.source):"cli",specHint:n.specHint!=null&&String(n.specHint).trim()!==""?String(n.specHint).trim().slice(0,240):"",studioTestCaseId:l},f=!1,p=0,B=()=>{try{I(u,c)}catch{}};try{for(;;){let w=!1;if(await pt(u,async()=>{if(N(u,{recursive:!0}),p=v(a,{reconcile:{}}).length,p<s){I(u,c),w=!0;return}W(u,{...y,updatedAt:Date.now()})}),w)return{waited:f,jobId:c};f||(typeof o=="function"&&o(`Waiting for run capacity (${p}/${s} active)\u2026`),f=!0),await new Promise(T=>setTimeout(T,i))}}finally{B()}}export{at as resolveRunCapacityPaths,Mt as waitUntilRunCapacity};
@@ -1,2 +1,2 @@
1
- import{existsSync as s,mkdirSync as N,readFileSync as g,renameSync as h,unlinkSync as v,writeFileSync as w}from"fs";import{join as f}from"path";function m(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(n){let r=n&&typeof n=="object"?n.code:"";return r==="ESRCH"?!1:r==="EPERM"?!0:null}}var S="run-capacity-wait.json",c=1,E=10800*1e3;function x(t){return f(t,S)}function _(t){return!t||typeof t!="string"?null:f(f(t,".."),S)}function a(){return{v:c,entries:[]}}function l(t){if(!t||!s(t))return a();let e=x(t);if(!s(e))return a();try{let n=g(e,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object")return a();let i=Array.isArray(r.entries)?r.entries:[];return{v:c,entries:i}}catch{return a()}}function p(t,e=Date.now()){let n=t&&Array.isArray(t.entries)?t.entries:[],r=[];for(let i of n){if(!i||typeof i!="object")continue;let u=Number(i.pid),o=Number(i.updatedAt)||Number(i.enqueuedAt)||0,y=Number.isFinite(u)&&u>0?m(u):null;y!==!1&&(y===null&&o>0&&e-o>E||r.push(i))}return{v:c,entries:r}}function d(t,e){let n=x(t);N(t,{recursive:!0});let r={v:c,entries:Array.isArray(e.entries)?e.entries:[]},i=`${n}.${process.pid}.${Date.now()}.tmp`;w(i,`${JSON.stringify(r)}
2
- `,"utf8");try{s(n)&&v(n)}catch{}h(i,n)}function A(t,e){let n=p(l(t)),r=e?.id!=null?String(e.id):"";if(!r)return;let i=n.entries.filter(o=>o&&String(o.id)!==r),u=Date.now();i.push({...e,id:r,pid:Number.isFinite(Number(e.pid))?Number(e.pid):process.pid,enqueuedAt:Number(e.enqueuedAt)||u,updatedAt:u}),d(t,{v:c,entries:i})}function O(t,e){let n=e!=null?String(e):"";if(!n||!t)return;let r=p(l(t)),i=r.entries.filter(u=>u&&String(u.id)!==n);i.length!==r.entries.length&&d(t,{v:c,entries:i})}function j(t){let e=l(t),n=p(e);return n.entries.length!==e.entries.length&&d(t,n),n.entries}export{S as RUN_CAPACITY_QUEUE_FILENAME,l as readRunCapacityQueueDoc,j as readRunCapacityWaitSnapshot,p as reconcileRunCapacityQueueDoc,O as removeRunCapacityQueueEntry,x as runCapacityQueuePathFromOutputDir,_ as runCapacityQueuePathFromSessionsRoot,A as upsertRunCapacityQueueEntry,d as writeRunCapacityQueueDocAtomic};
1
+ import{existsSync as s,mkdirSync as N,readFileSync as g,renameSync as h,unlinkSync as v,writeFileSync as w}from"node:fs";import{join as f}from"node:path";import{existsSync as F,mkdirSync as C,readFileSync as R,readdirSync as _,statSync as A,writeFileSync as O}from"node:fs";import{join as P}from"node:path";function m(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(n){let r=n&&typeof n=="object"?n.code:"";return r==="ESRCH"?!1:r==="EPERM"?!0:null}}var S="run-capacity-wait.json",c=1,E=10800*1e3;function x(t){return f(t,S)}function T(t){return!t||typeof t!="string"?null:f(f(t,".."),S)}function a(){return{v:c,entries:[]}}function l(t){if(!t||!s(t))return a();let e=x(t);if(!s(e))return a();try{let n=g(e,"utf8"),r=JSON.parse(n);if(!r||typeof r!="object")return a();let i=Array.isArray(r.entries)?r.entries:[];return{v:c,entries:i}}catch{return a()}}function p(t,e=Date.now()){let n=t&&Array.isArray(t.entries)?t.entries:[],r=[];for(let i of n){if(!i||typeof i!="object")continue;let u=Number(i.pid),o=Number(i.updatedAt)||Number(i.enqueuedAt)||0,y=Number.isFinite(u)&&u>0?m(u):null;y!==!1&&(y===null&&o>0&&e-o>E||r.push(i))}return{v:c,entries:r}}function d(t,e){let n=x(t);N(t,{recursive:!0});let r={v:c,entries:Array.isArray(e.entries)?e.entries:[]},i=`${n}.${process.pid}.${Date.now()}.tmp`;w(i,`${JSON.stringify(r)}
2
+ `,"utf8");try{s(n)&&v(n)}catch{}h(i,n)}function $(t,e){let n=p(l(t)),r=e?.id!=null?String(e.id):"";if(!r)return;let i=n.entries.filter(o=>o&&String(o.id)!==r),u=Date.now();i.push({...e,id:r,pid:Number.isFinite(Number(e.pid))?Number(e.pid):process.pid,enqueuedAt:Number(e.enqueuedAt)||u,updatedAt:u}),d(t,{v:c,entries:i})}function L(t,e){let n=e!=null?String(e):"";if(!n||!t)return;let r=p(l(t)),i=r.entries.filter(u=>u&&String(u.id)!==n);i.length!==r.entries.length&&d(t,{v:c,entries:i})}function J(t){let e=l(t),n=p(e);return n.entries.length!==e.entries.length&&d(t,n),n.entries}export{S as RUN_CAPACITY_QUEUE_FILENAME,l as readRunCapacityQueueDoc,J as readRunCapacityWaitSnapshot,p as reconcileRunCapacityQueueDoc,L as removeRunCapacityQueueEntry,x as runCapacityQueuePathFromOutputDir,T as runCapacityQueuePathFromSessionsRoot,$ as upsertRunCapacityQueueEntry,d as writeRunCapacityQueueDocAtomic};
@@ -1,4 +1,4 @@
1
- import{existsSync as R,readdirSync as U,statSync as X}from"fs";import{join as a,relative as v,sep as x,resolve as m}from"path";import{appendFileSync as Z,readFileSync as H,existsSync as B,mkdirSync as W}from"fs";import{join as w}from"path";var I=".zibby/output",_="sessions";var y="run-index.jsonl";function b(e,t=I){let n=w(e,t);return w(n,y)}function h(e){if(!e||!e.sessionId)return;let t=e.cwd||process.cwd(),n=e.outputBase||I,s=w(t,n);B(s)||W(s,{recursive:!0});let r=w(s,y),i=`${JSON.stringify(e)}
1
+ import{existsSync as R,readdirSync as U,statSync as X}from"fs";import{join as a,relative as v,sep as x,resolve as m}from"path";import{appendFileSync as Z,readFileSync as H,existsSync as B,mkdirSync as W}from"node:fs";import{join as w}from"node:path";var I=".zibby/output",_="sessions";var y="run-index.jsonl";function b(e,t=I){let n=w(e,t);return w(n,y)}function h(e){if(!e||!e.sessionId)return;let t=e.cwd||process.cwd(),n=e.outputBase||I,s=w(t,n);B(s)||W(s,{recursive:!0});let r=w(s,y),i=`${JSON.stringify(e)}
2
2
  `;Z(r,i,"utf8")}function O(e){if(!e||!B(e))return[];let t;try{t=H(e,"utf8")}catch{return[]}let n=[];for(let s of t.split(`
3
- `)){let r=s.trim();if(r)try{n.push(JSON.parse(r))}catch{}}return n}import{existsSync as z,mkdirSync as K,readFileSync as J,readdirSync as de,statSync as fe,writeFileSync as $}from"fs";import{join as G}from"path";var V="zibby-run-state.json";function A(e){return G(e,V)}function E(e){if(!e||typeof e!="string")return null;let t=A(e);if(!z(t))return null;try{let n=J(t,"utf8"),s=JSON.parse(n);return s&&typeof s=="object"?s:null}catch{return null}}function T(e,t){if(!e||typeof e!="string")return;try{K(e,{recursive:!0})}catch{return}let s={...E(e)||{v:1},...t,v:1,updatedAt:Date.now()};try{$(A(e),`${JSON.stringify(s)}
3
+ `)){let r=s.trim();if(r)try{n.push(JSON.parse(r))}catch{}}return n}import{existsSync as z,mkdirSync as K,readFileSync as J,readdirSync as de,statSync as fe,writeFileSync as $}from"node:fs";import{join as G}from"node:path";var V="zibby-run-state.json";function A(e){return G(e,V)}function E(e){if(!e||typeof e!="string")return null;let t=A(e);if(!z(t))return null;try{let n=J(t,"utf8"),s=JSON.parse(n);return s&&typeof s=="object"?s:null}catch{return null}}function T(e,t){if(!e||typeof e!="string")return;try{K(e,{recursive:!0})}catch{return}let s={...E(e)||{v:1},...t,v:1,updatedAt:Date.now()};try{$(A(e),`${JSON.stringify(s)}
4
4
  `,"utf8")}catch(r){console.warn(`[zibby run-state] ${r.message}`)}}function Q(e){return e?.recordKind==="progress"}function D(e){let t=Number(e)||0;return t<=0?0:t<1e12?t*1e3:t}function M(e,t={}){let n=t.maxProgressAgeMs!=null&&Number.isFinite(t.maxProgressAgeMs)?Math.max(0,t.maxProgressAgeMs):21e5,s=typeof t.now=="number"?t.now:Date.now(),{summary:r,progress:i}=e||{};if(!i)return!1;let o=D(i.ts);if(n>0&&o>0&&s-o>n)return!1;if(!r)return o>0;let d=D(r.ts);return o>d}function C(e){let t=new Map;for(let n of e||[]){if(!n?.sessionId)continue;let s=t.get(n.sessionId);s||(s={summary:null,progress:null});let r=Number(n.ts)||0;Q(n)?(!s.progress||r>=(Number(s.progress.ts)||0))&&(s.progress=n):(!s.summary||r>=(Number(s.summary.ts)||0))&&(s.summary=n),t.set(n.sessionId,s)}return t}var P=Object.freeze(["preflight","execute_live","generate_script"]);function N(e){let t=process.env.ZIBBY_STUDIO_TEST_CASE_ID;return t!=null&&String(t).trim()!==""?String(t).trim():e!=null?String(e):""}var q=[a("generate_script","generated-test.spec.js"),a("generate_script","generated-test.spec.ts"),a("generate_script","playwright.spec.ts"),a("generate_script","test.spec.ts")];function ee(e){let t=[a(e,"execute_live","videos"),a(e,"execute_live"),e];for(let n of t){if(!R(n))continue;let s;try{s=U(n)}catch{continue}let r=s.find(i=>i.endsWith(".webm"));if(r)return a(n,r)}return null}function te(e){let t=[a(e,"execute_live","events.json"),a(e,"events.json")];for(let n of t)if(R(n))return n;return null}function ne(e){for(let t of q){let n=a(e,t);if(R(n))return n}return null}function se(e){return!e||!R(e)?{videoPathAbs:null,eventsPathAbs:null,scriptPathAbs:null}:{videoPathAbs:ee(e),eventsPathAbs:te(e),scriptPathAbs:ne(e)}}function L(e){let t=e.cwd||process.cwd(),n=e.outputBase||I,i=((e.result||{}).state||{}).sessionPath;if(!i||typeof i!="string")return null;let o=i.split(/[/\\]/).filter(Boolean).pop();if(!o)return null;let{videoPathAbs:d,eventsPathAbs:f,scriptPathAbs:l}=se(i),p=u=>{if(!u)return null;try{return v(t,u).split(x).join("/")}catch{return null}},c=null;if(e.specPath)try{let u=m(t,e.specPath);c=v(t,u).split(x).join("/")}catch{c=String(e.specPath).split(x).join("/")}return{v:1,recordKind:"summary",ts:Date.now(),sessionId:o,status:e.status??(e.success?"completed":"failed"),cwd:t,outputBase:n,sessionPathAbs:i,sessionDirRel:p(i),videoPathAbs:d||null,eventsPathAbs:f||null,scriptPathAbs:l||null,videoRel:p(d),eventsRel:p(f),scriptRel:p(l),specRel:c,source:process.env.ZIBBY_RUN_SOURCE||"cli",studioTestCaseId:N(o)||null,errorMessage:e.errorMessage||null}}function F({cwd:e,config:t,result:n,success:s,specPath:r,errorMessage:i}){try{let o=L({cwd:e||process.cwd(),result:n,success:s,outputBase:t?.paths?.output||I,specPath:r,errorMessage:i});o&&(h(o),o.sessionPathAbs&&T(o.sessionPathAbs,{sessionId:o.sessionId,studioTestCaseId:o.studioTestCaseId||o.sessionId,status:o.status,activeNode:null,activeStageIndex:null,errorMessage:o.errorMessage||null,runSource:o.source||"cli",cwd:o.cwd,outputBase:o.outputBase,sessionPathAbs:o.sessionPathAbs}))}catch(o){console.warn(`[zibby browser-test run-index] ${o.message}`)}}function re({sessionPath:e,sessionId:t,cwd:n,outputBase:s=I}={}){let r=n||process.cwd(),i=s||I,o=t!=null&&String(t).trim()!==""?String(t).trim():null,d=process.env.ZIBBY_RUN_SOURCE==="studio",f=process.env.ZIBBY_SESSION_PATH&&String(process.env.ZIBBY_SESSION_PATH).trim();if(d&&f)return m(f);let l=e&&String(e).trim();if(l)return m(l);let p=process.env.ZIBBY_SESSIONS_ROOT&&String(process.env.ZIBBY_SESSIONS_ROOT).trim();return p&&o?m(a(p,o)):process.env.ZIBBY_SESSION_PATH&&String(process.env.ZIBBY_SESSION_PATH).trim()?m(String(process.env.ZIBBY_SESSION_PATH).trim()):m(a(r,i,_,o||"invalid"))}function oe(e){try{let t=e?.currentNode;if(!t||!P.includes(t))return;let n=e.sessionPath,s=e.sessionId||n&&String(n).split(/[/\\]/).filter(Boolean).pop()||null;if(!s)return;let r=e.cwd||process.cwd(),i=e.outputBase||I,o=P.indexOf(t),d=e?.specPath!=null?String(e.specPath).trim():"",f=e?.taskDescription!=null?String(e.taskDescription):"",l=null;if(d)try{let c=m(r,d);l=v(r,c).split(x).join("/")}catch{l=d.split(x).join("/")}let p=re({sessionPath:n,sessionId:s,cwd:r,outputBase:i});h({v:1,recordKind:"progress",ts:Date.now(),sessionId:s,cwd:r,outputBase:i,sessionPathAbs:p,activeNode:t,activeStageIndex:o,specRel:l,taskDescription:f||null,studioTestCaseId:N(s)||null,source:process.env.ZIBBY_RUN_SOURCE||"cli"}),T(p,{sessionId:s,studioTestCaseId:N(s)||s,status:"running",activeNode:t,activeStageIndex:o,sessionPathAbs:p,cwd:r,outputBase:i,specPath:l||null,task:f||null,taskDescription:f||null,runSource:process.env.ZIBBY_RUN_SOURCE||"cli",pid:typeof process.pid=="number"?process.pid:null})}catch(t){console.warn(`[zibby browser-test run-index progress] ${t.message}`)}}function k({cwd:e,config:t}={}){let n=e||process.cwd(),s=t?.paths?.output||I;return r=>{oe({cwd:r?.cwd||n,outputBase:r?.outputBase||s,sessionPath:r?.sessionPath,sessionId:r?.sessionId,currentNode:r?.currentNode,specPath:r?.specPath,taskDescription:r?.taskDescription})}}function j(e={}){try{let t=e.cwd||process.cwd(),n=e.config?.paths?.output||e.outputBase||I,s=b(t,n),r=O(s),i=C(r),o=new Set,d=e.errorMessage||"Run stopped (SIGINT/SIGTERM) before a normal summary was written.",f=(c,u)=>{if(!c||!u||o.has(c))return;o.add(c);let S=L({cwd:t,outputBase:n,result:{state:{sessionPath:u}},success:!1,specPath:null,status:"interrupted",errorMessage:d});S&&(h(S),T(u,{sessionId:c,studioTestCaseId:S.studioTestCaseId||c,status:"interrupted",activeNode:null,activeStageIndex:null,errorMessage:S.errorMessage||null,runSource:S.source||"cli",cwd:t,outputBase:n,sessionPathAbs:u}))};for(let[c,u]of i){if(!M(u))continue;let S=u.progress;if(!S)continue;let g=String(c),Y=S.sessionPathAbs&&String(S.sessionPathAbs)||a(t,n,_,g);f(g,Y)}let l=a(t,n,_);if(!R(l))return;let p;try{p=U(l)}catch{return}for(let c of p){let u=a(l,c),S;try{S=X(u)}catch{continue}if(!S.isDirectory())continue;let g=E(u);!g||g.status!=="running"||f(String(c),u)}}catch(t){console.warn(`[zibby browser-test run-index interrupt] ${t.message}`)}}function Ne(e){F(e)}function Be(e){j(e)}function ye(e){return k(e)}export{ye as createCliRunIndexPipelineProgressAppender,Be as postCliInterruptedRunIndex,Ne as postCliRunIndex};
@@ -1,3 +1,3 @@
1
- import{appendFileSync as p,readFileSync as _,existsSync as c,mkdirSync as S}from"fs";import{join as r}from"path";var i=".zibby/output";var u="run-index.jsonl";function O(t,n=i){let o=r(t,n);return r(o,u)}function x(t){if(!t||!t.sessionId)return;let n=t.cwd||process.cwd(),o=t.outputBase||i,s=r(n,o);c(s)||S(s,{recursive:!0});let e=r(s,u),I=`${JSON.stringify(t)}
1
+ import{appendFileSync as p,readFileSync as _,existsSync as c,mkdirSync as S}from"node:fs";import{join as r}from"node:path";var i=".zibby/output";var u="run-index.jsonl";function O(t,n=i){let o=r(t,n);return r(o,u)}function x(t){if(!t||!t.sessionId)return;let n=t.cwd||process.cwd(),o=t.outputBase||i,s=r(n,o);c(s)||S(s,{recursive:!0});let e=r(s,u),I=`${JSON.stringify(t)}
2
2
  `;p(e,I,"utf8")}function a(t){if(!t||!c(t))return[];let n;try{n=_(t,"utf8")}catch{return[]}let o=[];for(let s of n.split(`
3
3
  `)){let e=s.trim();if(e)try{o.push(JSON.parse(e))}catch{}}return o}function d(t){let n=new Map;for(let o of t){if(!o?.sessionId)continue;let s=n.get(o.sessionId),e=Number(o.ts)||0;(!s||e>=(Number(s.ts)||0))&&n.set(o.sessionId,o)}return n}export{u as RUN_INDEX_FILENAME,x as appendRunIndexRecord,d as latestRunRecordsBySession,a as readRunIndexRecordsFromFile,O as resolveRunIndexPath};
@@ -1,2 +1,2 @@
1
- import{existsSync as S,mkdirSync as g,readFileSync as h,readdirSync as x,statSync as N,writeFileSync as w}from"fs";import{join as m}from"path";function v(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(n){let r=n&&typeof n=="object"?n.code:"";return r==="ESRCH"?!1:r==="EPERM"?!0:null}}function F(t,e={}){if(!t||!S(t))return{patched:0};let n=e.studioNoPidMaxAgeMs!=null&&Number.isFinite(e.studioNoPidMaxAgeMs)?Math.max(0,e.studioNoPidMaxAgeMs):120*1e3,r=Date.now(),u=0,o;try{o=x(t)}catch{return{patched:0}}for(let s of o){let c=m(t,s),a;try{a=N(c)}catch{continue}if(!a.isDirectory())continue;let i=p(c);if(!i||i.status!=="running")continue;let l=Number(i.updatedAt)||0,y=v(i.pid),f=!1,d="";y===!1?(f=!0,d="process-exited"):y===null&&i.runSource==="studio"&&n>0&&l>0&&r-l>n&&(f=!0,d="studio-stale-no-pid"),f&&(D(c,{status:"interrupted",activeNode:null,activeStageIndex:null,exitReason:d}),u+=1)}return{patched:u}}var E="zibby-run-state.json";function M(t){return m(t,E)}function p(t){if(!t||typeof t!="string")return null;let e=M(t);if(!S(e))return null;try{let n=h(e,"utf8"),r=JSON.parse(n);return r&&typeof r=="object"?r:null}catch{return null}}function D(t,e){if(!t||typeof t!="string")return;try{g(t,{recursive:!0})}catch{return}let r={...p(t)||{v:1},...e,v:1,updatedAt:Date.now()};try{w(M(t),`${JSON.stringify(r)}
1
+ import{existsSync as S,mkdirSync as g,readFileSync as h,readdirSync as x,statSync as N,writeFileSync as w}from"node:fs";import{join as m}from"node:path";function v(t){let e=Number(t);if(!Number.isFinite(e)||e<=0)return null;try{return process.kill(e,0),!0}catch(n){let r=n&&typeof n=="object"?n.code:"";return r==="ESRCH"?!1:r==="EPERM"?!0:null}}function F(t,e={}){if(!t||!S(t))return{patched:0};let n=e.studioNoPidMaxAgeMs!=null&&Number.isFinite(e.studioNoPidMaxAgeMs)?Math.max(0,e.studioNoPidMaxAgeMs):120*1e3,r=Date.now(),u=0,o;try{o=x(t)}catch{return{patched:0}}for(let s of o){let c=m(t,s),a;try{a=N(c)}catch{continue}if(!a.isDirectory())continue;let i=p(c);if(!i||i.status!=="running")continue;let l=Number(i.updatedAt)||0,y=v(i.pid),f=!1,d="";y===!1?(f=!0,d="process-exited"):y===null&&i.runSource==="studio"&&n>0&&l>0&&r-l>n&&(f=!0,d="studio-stale-no-pid"),f&&(D(c,{status:"interrupted",activeNode:null,activeStageIndex:null,exitReason:d}),u+=1)}return{patched:u}}var E="zibby-run-state.json";function M(t){return m(t,E)}function p(t){if(!t||typeof t!="string")return null;let e=M(t);if(!S(e))return null;try{let n=h(e,"utf8"),r=JSON.parse(n);return r&&typeof r=="object"?r:null}catch{return null}}function D(t,e){if(!t||typeof t!="string")return;try{g(t,{recursive:!0})}catch{return}let r={...p(t)||{v:1},...e,v:1,updatedAt:Date.now()};try{w(M(t),`${JSON.stringify(r)}
2
2
  `,"utf8")}catch(u){console.warn(`[zibby run-state] ${u.message}`)}}function P(t,e={}){if(!t||!S(t))return[];e.reconcile!==!1&&F(t,e.reconcile||{});let n=e.maxStaleMs!=null&&Number.isFinite(e.maxStaleMs)&&e.maxStaleMs>0?e.maxStaleMs:1800*1e3,r=typeof e.now=="number"?e.now:Date.now(),u;try{u=x(t)}catch{return[]}let o=[];for(let s of u){let c=m(t,s),a;try{a=N(c)}catch{continue}if(!a.isDirectory())continue;let i=p(c);if(!i||i.status!=="running")continue;let l=Number(i.updatedAt)||0;n>0&&l>0&&r-l>n||o.push({sessionId:s,sessionPathAbs:c,...i})}return o}export{E as SESSION_RUN_STATE_FILENAME,P as listRunningSessionStatesFromSessionsRoot,D as mergeSessionRunState,v as processPidLooksAlive,p as readSessionRunState,F as reconcileStaleRunningSessionStates,M as sessionRunStateFilePath};
@@ -1,2 +1,2 @@
1
- import{readFileSync as W,existsSync as F,readdirSync as O}from"fs";import{join as N}from"path";import{execSync as L}from"child_process";import{tmpdir as B}from"os";var v=class{static async parseTraceZip(h){let o;if(h.endsWith(".zip")&&F(h)){let n=N(B(),`trace-${Date.now()}`);L(`unzip -q "${h}" -d "${n}"`,{stdio:"pipe"});let a=O(n).find(c=>c.endsWith(".trace"));if(!a)throw new Error("No .trace file found in zip");o=N(n,a)}else if(F(h)){let u=O(h).find(a=>a.endsWith(".trace"));if(!u)throw new Error("No .trace file found");o=N(h,u)}else throw new Error(`Trace not found at ${h}`);try{let u=W(o,"utf-8").trim().split(`
1
+ import{readFileSync as W,existsSync as F,readdirSync as O}from"node:fs";import{join as N}from"node:path";import{execSync as L}from"node:child_process";import{tmpdir as B}from"node:os";var v=class{static async parseTraceZip(h){let o;if(h.endsWith(".zip")&&F(h)){let n=N(B(),`trace-${Date.now()}`);L(`unzip -q "${h}" -d "${n}"`,{stdio:"pipe"});let a=O(n).find(c=>c.endsWith(".trace"));if(!a)throw new Error("No .trace file found in zip");o=N(n,a)}else if(F(h)){let u=O(h).find(a=>a.endsWith(".trace"));if(!u)throw new Error("No .trace file found");o=N(h,u)}else throw new Error(`Trace not found at ${h}`);try{let u=W(o,"utf-8").trim().split(`
2
2
  `),a=[],c=new Map,r=new Map;for(let w of u)try{let t=JSON.parse(w);if(t.type==="snapshot"&&t.snapshot&&t.snapshot.accessibility){let l=new Map;for(let i of t.snapshot.accessibility)i.ref&&l.set(i.ref,i);c.set(t.snapshotName,l)}if(t.type==="frame-snapshot"&&t.snapshot){let l=Buffer.from(t.snapshot.html||"","base64").toString("utf-8");l&&l.length>100&&r.set(t.pageId||"default",l)}}catch{}for(let w of u)try{let t=JSON.parse(w);if(t.type==="before"&&t.params&&t.params.selector){let l=t.method;if(["click","fill","type","selectOption"].includes(l)){let i=t.params.selector,z=t.params.text||t.params.value||"",e=[],p=null,f=null,m=null,R=i.match(/aria-ref=([a-z0-9]+)/i);if(R&&t.snapshotName){let s=R[1],x=c.get(t.snapshotName);if(x&&x.has(s)){let y=x.get(s);p=y.name||null,f=y.role||null,m=y.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${p}", role="${f}"`)}}let d=i.match(/internal:text="([^"]+)"/i),E=i.match(/internal:label="([^"]+)"/i),C=i.match(/internal:placeholder="([^"]+)"/i),T=i.match(/internal:role=([^ ]+)/i),M=i.match(/internal:describe="([^"]+)"/i),k=i.match(/name="([^"]+)"/i);if(d){e.push({type:"text",text:d[1]});let s=d[1].split(" ");s.length>1&&(e.push({type:"text",text:s[0],fuzzy:!0}),e.push({type:"text",text:s[s.length-1],fuzzy:!0}))}if(E&&e.push({type:"label",label:E[1]}),C&&e.push({type:"placeholder",placeholder:C[1]}),p){e.unshift({type:"text",text:p,source:"accessibility-tree"});let s=p.split(" ");s.length>1&&e.push({type:"text",text:s[0],fuzzy:!0,source:"accessibility-tree"})}if(f||T){let s=f||T[1],x=p||(k?k[1]:d?d[1]:null);e.unshift({type:"role",role:s,name:x,source:p?"accessibility-tree":"selector"})}if(m&&e.unshift({type:"label",label:m,source:"accessibility-tree"}),M){let s=M[1],x=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],y=null,$=s;for(let g of x)if(s.toLowerCase().endsWith(` ${g}`)){y=g.replace(" ",""),$=s.substring(0,s.length-g.length-1);break}if(y){e.push({type:"role",role:y,name:$});let g=$.replace(/\s*\([^)]+\)\s*$/,"");e.push({type:"text",text:g}),e.push({type:"text",text:$});let S=$.split(" ");S.length>1&&(e.push({type:"text",text:S[0],fuzzy:!0}),e.push({type:"text",text:S.slice(0,2).join(" "),fuzzy:!0}))}else{let g=s.replace(/\s*\([^)]+\)\s*$/,"");e.push({type:"text",text:g}),e.push({type:"text",text:s})}}let A=this.extractDOMStrategies(i,r,d?.[1]||M?.[1],t.pageId);e.push(...A);let b=this.extractStructuralContext(i);(b.parent||b.sibling)&&e.forEach(s=>{["role","text","label","testid"].includes(s.type)&&(b.parent&&(s.parent=b.parent),b.sibling&&(s.sibling=b.sibling))}),e.push({type:"css",value:i});let j=p||d?d[1]:M?M[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${a.length}`;a.push({method:l,name:j,action:l==="type"?"fill":l,value:z,strategies:e,timestamp:t.startTime,actualText:p,actualRole:f,actualAriaLabel:m})}}}catch{}return a}catch(n){throw new Error(`Failed to parse trace: ${n.message}`,{cause:n})}}static extractDOMStrategies(h,o,n,u){let a=[];if(!o||o.size===0||!n)return a;try{let c=o.get(u);if(!c)return a;let r=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),w=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${r}`,"i"),t=c.match(w);t&&a.push({type:"testid",value:t[1],priority:"high"});let l=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${r}`,"gi"),i=c.matchAll(l);for(let p of i){let f=p[1].split(/\s+/).filter(m=>m&&!m.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&m.length>2);f.length>0&&(a.push({type:"class",value:f.join("."),priority:"medium"}),f.length===1&&a.push({type:"class",value:f[0],priority:"medium"}))}let z=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${r}`,"i"),e=c.match(z);e&&!e[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&a.push({type:"id",value:e[1],priority:"high"})}catch(c){console.warn(`[TraceParser] DOM extraction failed: ${c.message}`)}return a}static extractStructuralContext(h){let o={parent:null,sibling:null},n=h.split(">>").map(c=>c.trim());if(n.length>1){let r=n[n.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();r&&(r.match(/^(form|section|nav|header|aside|main|article)\b/)||r.includes("[")||r.match(/[#.]\w/))&&(o.parent=r)}let a=n[n.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return a&&(o.sibling=a[1].trim()),o}},U=v;export{v as TraceParser,U as default};
@@ -1,3 +1,3 @@
1
- import{readdir as v,access as h,copyFile as w,constants as g}from"fs/promises";import{join as i,relative as $}from"path";async function F(c={}){let{testResultsDir:a="test-results",testsDir:o="tests",projectRoot:t=process.cwd(),verbose:s=!0}=c;s&&console.log(`\u{1F3A5} Organizing test videos...
1
+ import{readdir as v,access as h,copyFile as w,constants as g}from"fs/promises";import{join as i,relative as $}from"node:path";async function F(c={}){let{testResultsDir:a="test-results",testsDir:o="tests",projectRoot:t=process.cwd(),verbose:s=!0}=c;s&&console.log(`\u{1F3A5} Organizing test videos...
2
2
  `);let r=i(t,a),l=i(t,o);try{let e=await v(r),f=0;for(let n of e){if(n.startsWith("."))continue;let u=i(r,n,"video.webm");try{await h(u,g.F_OK)}catch{continue}let m=n.replace(/-chromium$/,"").replace(/-firefox$/,"").replace(/-webkit$/,""),d=await P(l,m);if(d){let p=d.replace(/\.spec\.(js|ts)$/,".spec.webm");await w(u,p),s&&console.log(`\u2705 ${$(t,p)}`),f++}else s&&console.log(`\u26A0\uFE0F Could not find test file for: ${n}`)}return s&&(console.log(`
3
3
  \u{1F3AC} Organized ${f} video(s)`),console.log(`\u{1F4C2} Videos are now next to their test files in ${o}/`)),{movedCount:f,success:!0}}catch(e){return s&&console.error("\u274C Error organizing videos:",e.message),{movedCount:0,success:!1,error:e.message}}}async function P(c,a){let o=a.split("-");for(let t=o.length;t>0;t--){let r=o.slice(0,t).join("/");for(let l of["js","ts"]){let e=i(c,`${r}.spec.${l}`);try{return await h(e,g.F_OK),e}catch{}}}return null}export{F as organizeVideos};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/core",
3
- "version": "0.1.34",
3
+ "version": "0.1.37",
4
4
  "description": "Core test automation engine with multi-agent and multi-MCP support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",