@zibby/cli 0.1.33 → 0.1.35
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.
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{dirname as
|
|
3
|
-
`);n=
|
|
4
|
-
`);e!==E&&e.length>0&&(E=e,
|
|
5
|
-
`),
|
|
6
|
-
`)}))},500);try{await
|
|
7
|
-
`);if(
|
|
8
|
-
`),e.success){await
|
|
2
|
+
import{dirname as T,join as O,resolve as j}from"path";import{fileURLToPath as b}from"url";import{readFileSync as R,existsSync as L}from"fs";import{compileGraph as A,validateGraphConfig as G}from"@zibby/core/framework/graph-compiler.js";import{WorkflowGraph as J}from"@zibby/core/framework/graph.js";import{buildAnalysisGraph as U}from"@zibby/core/templates/code-analysis/graph.js";import{analysisStateSchema as z}from"@zibby/core/templates/code-analysis/state.js";import"@zibby/core/templates/register-nodes.js";import{fetchExecutionContext as D}from"../utils/execution-context.js";import{reportProgress as W,reportArtifact as K,reportFinalStatus as M}from"../utils/progress-reporter.js";import{writeMcpConfig as N}from"@zibby/core/utils/mcp-config-writer.js";const F=b(import.meta.url),B=T(F),q=JSON.parse(R(O(B,"../../package.json"),"utf-8")),H={analyze_ticket:t=>({key:"analysis",value:{raw:t.raw,structured:t.output}}),generate_code:t=>({key:"codeImplementation",value:t.output?.codeImplementation}),generate_test_cases:t=>({key:"tests",value:t.output?.tests}),finalize:t=>({key:"report",value:t.output?.report})};function Q(t,h){return async function(a,v,u){const I=Date.now(),f=[];let E="";const _=console.log,$=process.stdout.write.bind(process.stdout),p=process.stderr.write.bind(process.stderr);let S=!1;console.log=(...e)=>{const c=e.map(i=>typeof i=="string"?i:JSON.stringify(i)).join(" ");f.push(c),S=!0,_(...e),S=!1};let n="";process.stdout.write=(e,c,i)=>{if(!S){const s=typeof e=="string"?e:e.toString();n+=s;const d=n.split(`
|
|
3
|
+
`);n=d.pop()||"";for(const g of d){const m=g.trim();m&&f.push(m)}}return $(e,c,i)},_(`[Middleware] Started capturing logs for ${a}`);let y=!1;const C=setInterval(()=>{if(y)return;const e=f.join(`
|
|
4
|
+
`);e!==E&&e.length>0&&(E=e,p(`\u{1F4E1} [Middleware] Sending live update for ${a}: ${e.length} chars, ${f.length} lines
|
|
5
|
+
`),t(a,"in_progress",e,u).catch(c=>{p(`\u26A0\uFE0F [Middleware] Failed to send live update: ${c.message}
|
|
6
|
+
`)}))},500);try{await t(a,"in_progress","",u);const e=await v(),c=((Date.now()-I)/1e3).toFixed(1);y=!0,clearInterval(C),await new Promise(s=>setImmediate(s)),console.log=_,process.stdout.write=$,n.trim()&&(f.push(n.trim()),n="");const i=f.join(`
|
|
7
|
+
`);if(p(`\u{1F4E1} [Middleware] Sending final update for ${a}: ${i.length} chars, ${f.length} total lines captured
|
|
8
|
+
`),e.success){await t(a,"success",i||`Completed in ${c}s`,u);const s=H[a];if(s){const{key:d,value:g}=s(e);g&&await h(u,d,g)}}else await t(a,"failed",`${i}
|
|
9
9
|
|
|
10
|
-
Error: ${e.error}`,u);return e}catch(e){
|
|
10
|
+
Error: ${e.error}`,u);return e}catch(e){y=!0,clearInterval(C),await new Promise(i=>setImmediate(i)),console.log=_,process.stdout.write=$;const c=`${f.join(`
|
|
11
11
|
`)}
|
|
12
12
|
|
|
13
|
-
Error: ${e.message}`;throw await
|
|
14
|
-
\u{1F680} Zibby Analysis (Graph Mode)`),console.log(`@zibby/cli v${
|
|
15
|
-
\u{1F4CB} Validation: canProceed=${
|
|
16
|
-
\u{1F4CA} Sending final status: ${
|
|
17
|
-
\u2705 Analysis completed successfully`),process.exit(0)}catch(
|
|
18
|
-
\u274C Analysis failed:`,
|
|
13
|
+
Error: ${e.message}`;throw await t(a,"failed",c,u),e}}}async function X(t){const{EXECUTION_ID:h,TICKET_KEY:k,PROJECT_ID:a,REPOS:v,PROGRESS_QUEUE_URL:u,PROGRESS_API_URL:I,SQS_AUTH_TOKEN:f,PROJECT_API_TOKEN:E,GITHUB_TOKEN:_,MODEL:$}=process.env;(!h||!k||!a)&&(console.error("\u274C Missing required environment variables"),console.error(" Required: EXECUTION_ID, TICKET_KEY, PROJECT_ID"),process.exit(1));const p=await D(h,a),S=p.ticketContext;let n=p.nodeConfigs||{};const y=v?JSON.parse(v):p.repos,C=process.env.WORKSPACE||"/workspace",e=b(import.meta.resolve("@zibby/core")),c=O(T(e),"templates","code-analysis","prompts");console.log(`
|
|
14
|
+
\u{1F680} Zibby Analysis (Graph Mode)`),console.log(`@zibby/cli v${q.version} | Node.js ${process.version}`),console.log("\u2500".repeat(60)),console.log(`Ticket: ${k}`),console.log(`Repositories: ${y.length}`),console.log(`Workspace: ${C}`),console.log(`AI Model: ${$||"auto"}`),console.log("\u2500".repeat(60));const i=Q(W,K);let s,d,g=null;if(t?.workflow){const o=j(process.cwd(),t.workflow);if(L(o)||(console.error(`\u274C Workflow file not found: ${o}`),process.exit(1)),o.endsWith(".js")||o.endsWith(".mjs"))try{const{pathToFileURL:r}=await import("url");g=await import(r(o).href),d=`local JS module (${o})`}catch(r){console.error(`\u274C Failed to load workflow JS module: ${r.message}`),process.exit(1)}else{try{const l=JSON.parse(R(o,"utf-8")),{_meta:w,...P}=l;s=P,d=`local file (${o})`}catch(l){console.error(`\u274C Failed to parse workflow file: ${l.message}`),process.exit(1)}const r=G(s);r.valid||(console.error("\u274C Invalid workflow file:"),r.errors.forEach(l=>console.error(` - ${l}`)),process.exit(1))}}else if(p.graphConfig)s=p.graphConfig,d="custom (from project workflow)";else{const o=new J;U(o),s=o.serialize(),d="default"}let m;if(g){const r={...g.nodeConfigs||{},...n};m=g.buildGraph({nodeMiddleware:i}),console.log(`\u{1F4D0} Graph source: ${d}`),console.log(` Nodes: ${m.nodes.size}`),n=r}else{if(n&&Object.keys(n).length>0){const o=s.nodeConfigs||{},r={...o};for(const[l,w]of Object.entries(n))r[l]={...o[l],...w};s.nodeConfigs=r}console.log(`\u{1F4D0} Graph source: ${d}`),console.log(` Nodes: ${s.nodes?.length||0}`),console.log(` Edges: ${s.edges?.length||0}`),m=A(s,{nodeMiddleware:i,stateSchema:z})}N(n);const x={EXECUTION_ID:h,PROGRESS_QUEUE_URL:u,PROGRESS_API_URL:I,SQS_AUTH_TOKEN:f,PROJECT_API_TOKEN:E,workspace:C,repos:y,ticketContext:S,promptsDir:c,githubToken:_,model:$,nodeConfigs:n};try{const r=(await m.run(null,x)).state,l=r.analyze_ticket_output?.validation||r.analyze_ticket_output?.analysis?.structured?.validation;let w="completed";l&&!l.canProceed&&(w=l.status==="insufficient_context"?"insufficient_context":"blocked"),console.log(`
|
|
15
|
+
\u{1F4CB} Validation: canProceed=${l?.canProceed}, status=${l?.status}, finalStatus=${w}`),console.log(`
|
|
16
|
+
\u{1F4CA} Sending final status: ${w}`),await M(x,{status:w}),console.log(`
|
|
17
|
+
\u2705 Analysis completed successfully`),process.exit(0)}catch(o){if(console.error(`
|
|
18
|
+
\u274C Analysis failed:`,o.message),h)try{console.log("\u{1F4E1} Reporting failure..."),await M(x,{status:"failed",error:o.message})}catch{console.error("\u26A0\uFE0F Failed to report error")}process.exit(1)}}import.meta.url===`file://${process.argv[1]}`&&X();export{X as analyzeCommand};
|
package/dist/commands/studio.js
CHANGED
|
@@ -5,7 +5,7 @@ import It from"express";import{createServer as Jt}from"http";import{WebSocketSer
|
|
|
5
5
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
6
6
|
\u2551 Zibby Studio \u2551
|
|
7
7
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
8
|
-
`),ie({projectRoot:I}),setTimeout(()=>{y.close(),process.exit(0)},1e3)}function rt(){const s=a(I,".zibby.config.mjs");return u(s)?s:a(v,".zibby.config.mjs")}function x(){rt();const s=a(I,".zibby","output","sessions");return u(s)?s:a(v,".zibby","output","sessions")}function q(s,t){let e=null,o=null,n=null;const c=a(s,"codegen");if(u(c)){const r=a(c,"test.spec.ts"),i=a(c,"generated-test.spec.js");e=u(r)?r:u(i)?i:null;const d=a(c,"test.selenium.py"),p=a(c,"generated-test-selenium.js");o=u(d)?d:u(p)?p:null;const m=a(c,"trace.zip");n=u(m)?m:null}const l=a(s,"generate_script","result.json");if(!e&&u(l))try{const i=JSON.parse(_(l,"utf8"))?.scriptPath;if(typeof i=="string"&&i.trim()){const d=i.trim(),p=d.startsWith("/")||process.platform==="win32"&&/^[A-Za-z]:[\\/]/.test(d)?d:a(t,d);u(p)&&(e=p)}}catch(r){console.warn("[Studio API] generate_script result.json:",r.message)}return!e&&!o&&!n?null:{playwrightFile:e,seleniumFile:o,tracePath:n}}function Rt(s,t,e){try{H(a(s,U),JSON.stringify({sessionId:t,pid:e??null,startedAt:Date.now()},null,2),"utf8")}catch(o){console.error("[Studio API] writeStudioRunMeta:",o.message)}}function z(s){try{const t=a(s,U);u(t)&&qt(t)}catch{}}function Ct(s){const t=Number(s);if(!Number.isFinite(t)||t<=0)return[];try{const e=Y(`pgrep -P ${t}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:524288}).trim();return e?e.split(/\n/).map(o=>parseInt(o.trim(),10)).filter(o=>Number.isFinite(o)&&o>0):[]}catch{return[]}}function W(s,t){const e=Number(s);if(!Number.isFinite(e)||e<=0)return;const o=new Set;function n(c){if(!o.has(c)){o.add(c);for(const l of Ct(c))n(l);try{process.kill(c,t)}catch{}}}n(e)}function it(s){const t=Number(s);if(!(!Number.isFinite(t)||t<=0))try{Y(`taskkill /PID ${t} /T /F`,{stdio:"ignore",windowsHide:!0})}catch{}}function ct(s){if(!Number.isFinite(s)||s<=0)return;if(process.platform==="win32"){it(s);return}W(s,"SIGTERM");const t=setTimeout(()=>{W(s,"SIGKILL")},800);typeof t.unref=="function"&&t.unref()}function Ft(s,t){const o=C(s)||a(x(),s);try{bt(o,{recursive:!0}),H(a(o,Et),JSON.stringify({requestedAt:Date.now()}),"utf8")}catch(r){console.error("[Studio API] write studio stop request:",r.message)}const n=R.get(s);if(n){const r=n.pid;if(process.platform==="win32")it(r);else{W(r,"SIGTERM");const i=setTimeout(()=>{W(r,"SIGKILL")},800);typeof i.unref=="function"&&i.unref()}return R.delete(s),z(o),!0}const c=a(o,U);if(u(c)){let r=null;try{const i=JSON.parse(_(c,"utf8"));r=Number(i.pid)}catch(i){console.error("[Studio API] studio-run.json read:",i.message)}if(z(o),Number.isFinite(r)&&r>0)return ct(r),!0}const l=Number(t);return Number.isFinite(l)&&l>0?(ct(l),z(o),!0):!1}function J(s){try{const t=s?.query?.sessionsRoot;if(typeof t!="string")return"";const e=t.trim();if(!e)return"";const o=decodeURIComponent(e),n=O(o);return u(n)?n:""}catch{return""}}function C(s,t=""){const e=typeof s=="string"?decodeURIComponent(s).trim():String(s||"").trim();if(!e)return null;const o=[e],n=e.split("_")[0]?.trim()||"";n&&n!==e&&o.push(n);const c=new Set,l=[],r=new Set,i=[],d=h=>{if(!h)return;const f=O(h);r.has(f)||(r.add(f),i.push(f))},p=h=>{if(h){d(h);for(const f of o){const S=a(h,f);c.has(S)||(c.add(S),l.push(S))}}};p(t),p(x()),p(a(v,".zibby","output","sessions"));let m;try{m=$(I)}catch{m=[]}for(const h of m){if(h.startsWith("."))continue;const f=a(I,h);try{if(!L(f).isDirectory())continue}catch{continue}p(a(f,".zibby","output","sessions"));let S;try{S=$(f,{withFileTypes:!0})}catch{S=[]}for(const T of S)T?.isDirectory?.()&&String(T.name||"").startsWith(".zibby")&&p(a(f,T.name,"output","sessions"))}const w=l.filter(h=>u(h));if(w.length===0)for(const h of i){if(!u(h))continue;let f;try{f=$(h,{withFileTypes:!0})}catch{f=[]}for(const S of f){if(!S?.isDirectory?.())continue;const T=String(S.name||"");if(T===e||T===n||T.startsWith(`${e}_`)||n&&T.startsWith(`${n}_`)){const F=a(h,T);if(c.has(F))continue;c.add(F),w.push(F)}}}if(w.length===0)return null;if(w.length===1)return w[0];const M=h=>{let f=0;u(a(h,"execute_live"))&&(f+=20),Pt(h)&&(f+=15),u(a(h,"execute_live","events.json"))&&(f+=8),u(a(h,"execute_live","result.json"))&&(f+=6),u(a(h,U))&&(f+=4),u(a(h,".session-info.json"))&&(f+=2);try{const S=a(h,"execute_live");u(S)&&(f+=Math.min(L(S).mtimeMs/1e12,3))}catch{}return f};return w.sort((h,f)=>M(f)-M(h)),w[0]}function Lt(s,t){try{const e=typeof s=="string"?decodeURIComponent(s).trim():String(s||"").trim();if(!e||!t)return null;const o=(e.split("_")[0]||"").trim(),n=jt(t);if(!o||!n||!u(n))return null;let c=[];try{c=$(n,{withFileTypes:!0})}catch{c=[]}let l=null;for(const r of c){if(!r?.isDirectory?.())continue;const i=String(r.name||"");if(!(i===e||i===o||i.startsWith(`${e}_`)||i.startsWith(`${o}_`)))continue;const d=a(n,i),p=vt(d);p&&(!l||Number(p.mtime||0)>Number(l.mtime||0))&&(l=p)}return l}catch{return null}}g.get("/api/config/check",(s,t)=>{const e=rt();t.json({exists:u(e),path:e,isProjectLevel:e.startsWith(I)})}),g.get("/api/projects",(s,t)=>{try{const e=a(v,".zibby","config.json");if(!u(e))return t.json({projects:[]});const o=JSON.parse(_(e,"utf8")),n=typeof o.sessionToken=="string"&&o.sessionToken.trim()!==""?o.sessionToken.trim():"",c=Array.isArray(o.projects)?o.projects:[];if(!n)return t.json({projects:c});const l=String(wt()).replace(/\/$/,"");fetch(`${l}/projects`,{headers:{Authorization:`Bearer ${n}`}}).then(r=>r.json().catch(()=>({})).then(i=>({ok:r.ok,status:r.status,body:i}))).then(({ok:r,body:i})=>{if(!r)return t.json({projects:c});const p=(Array.isArray(i?.projects)?i.projects:[]).map(m=>({name:m?.name,projectId:m?.projectId,apiToken:m?.apiToken||null,createdAt:m?.createdAt||null,updatedAt:m?.updatedAt||null}));o.projects=p;try{H(e,`${JSON.stringify(o,null,2)}
|
|
8
|
+
`),await ie({projectRoot:I}),setTimeout(()=>{y.close(),process.exit(0)},1e3)}function rt(){const s=a(I,".zibby.config.mjs");return u(s)?s:a(v,".zibby.config.mjs")}function x(){rt();const s=a(I,".zibby","output","sessions");return u(s)?s:a(v,".zibby","output","sessions")}function q(s,t){let e=null,o=null,n=null;const c=a(s,"codegen");if(u(c)){const r=a(c,"test.spec.ts"),i=a(c,"generated-test.spec.js");e=u(r)?r:u(i)?i:null;const d=a(c,"test.selenium.py"),p=a(c,"generated-test-selenium.js");o=u(d)?d:u(p)?p:null;const m=a(c,"trace.zip");n=u(m)?m:null}const l=a(s,"generate_script","result.json");if(!e&&u(l))try{const i=JSON.parse(_(l,"utf8"))?.scriptPath;if(typeof i=="string"&&i.trim()){const d=i.trim(),p=d.startsWith("/")||process.platform==="win32"&&/^[A-Za-z]:[\\/]/.test(d)?d:a(t,d);u(p)&&(e=p)}}catch(r){console.warn("[Studio API] generate_script result.json:",r.message)}return!e&&!o&&!n?null:{playwrightFile:e,seleniumFile:o,tracePath:n}}function Rt(s,t,e){try{H(a(s,U),JSON.stringify({sessionId:t,pid:e??null,startedAt:Date.now()},null,2),"utf8")}catch(o){console.error("[Studio API] writeStudioRunMeta:",o.message)}}function z(s){try{const t=a(s,U);u(t)&&qt(t)}catch{}}function Ct(s){const t=Number(s);if(!Number.isFinite(t)||t<=0)return[];try{const e=Y(`pgrep -P ${t}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:524288}).trim();return e?e.split(/\n/).map(o=>parseInt(o.trim(),10)).filter(o=>Number.isFinite(o)&&o>0):[]}catch{return[]}}function W(s,t){const e=Number(s);if(!Number.isFinite(e)||e<=0)return;const o=new Set;function n(c){if(!o.has(c)){o.add(c);for(const l of Ct(c))n(l);try{process.kill(c,t)}catch{}}}n(e)}function it(s){const t=Number(s);if(!(!Number.isFinite(t)||t<=0))try{Y(`taskkill /PID ${t} /T /F`,{stdio:"ignore",windowsHide:!0})}catch{}}function ct(s){if(!Number.isFinite(s)||s<=0)return;if(process.platform==="win32"){it(s);return}W(s,"SIGTERM");const t=setTimeout(()=>{W(s,"SIGKILL")},800);typeof t.unref=="function"&&t.unref()}function Ft(s,t){const o=C(s)||a(x(),s);try{bt(o,{recursive:!0}),H(a(o,Et),JSON.stringify({requestedAt:Date.now()}),"utf8")}catch(r){console.error("[Studio API] write studio stop request:",r.message)}const n=R.get(s);if(n){const r=n.pid;if(process.platform==="win32")it(r);else{W(r,"SIGTERM");const i=setTimeout(()=>{W(r,"SIGKILL")},800);typeof i.unref=="function"&&i.unref()}return R.delete(s),z(o),!0}const c=a(o,U);if(u(c)){let r=null;try{const i=JSON.parse(_(c,"utf8"));r=Number(i.pid)}catch(i){console.error("[Studio API] studio-run.json read:",i.message)}if(z(o),Number.isFinite(r)&&r>0)return ct(r),!0}const l=Number(t);return Number.isFinite(l)&&l>0?(ct(l),z(o),!0):!1}function J(s){try{const t=s?.query?.sessionsRoot;if(typeof t!="string")return"";const e=t.trim();if(!e)return"";const o=decodeURIComponent(e),n=O(o);return u(n)?n:""}catch{return""}}function C(s,t=""){const e=typeof s=="string"?decodeURIComponent(s).trim():String(s||"").trim();if(!e)return null;const o=[e],n=e.split("_")[0]?.trim()||"";n&&n!==e&&o.push(n);const c=new Set,l=[],r=new Set,i=[],d=h=>{if(!h)return;const f=O(h);r.has(f)||(r.add(f),i.push(f))},p=h=>{if(h){d(h);for(const f of o){const S=a(h,f);c.has(S)||(c.add(S),l.push(S))}}};p(t),p(x()),p(a(v,".zibby","output","sessions"));let m;try{m=$(I)}catch{m=[]}for(const h of m){if(h.startsWith("."))continue;const f=a(I,h);try{if(!L(f).isDirectory())continue}catch{continue}p(a(f,".zibby","output","sessions"));let S;try{S=$(f,{withFileTypes:!0})}catch{S=[]}for(const T of S)T?.isDirectory?.()&&String(T.name||"").startsWith(".zibby")&&p(a(f,T.name,"output","sessions"))}const w=l.filter(h=>u(h));if(w.length===0)for(const h of i){if(!u(h))continue;let f;try{f=$(h,{withFileTypes:!0})}catch{f=[]}for(const S of f){if(!S?.isDirectory?.())continue;const T=String(S.name||"");if(T===e||T===n||T.startsWith(`${e}_`)||n&&T.startsWith(`${n}_`)){const F=a(h,T);if(c.has(F))continue;c.add(F),w.push(F)}}}if(w.length===0)return null;if(w.length===1)return w[0];const M=h=>{let f=0;u(a(h,"execute_live"))&&(f+=20),Pt(h)&&(f+=15),u(a(h,"execute_live","events.json"))&&(f+=8),u(a(h,"execute_live","result.json"))&&(f+=6),u(a(h,U))&&(f+=4),u(a(h,".session-info.json"))&&(f+=2);try{const S=a(h,"execute_live");u(S)&&(f+=Math.min(L(S).mtimeMs/1e12,3))}catch{}return f};return w.sort((h,f)=>M(f)-M(h)),w[0]}function Lt(s,t){try{const e=typeof s=="string"?decodeURIComponent(s).trim():String(s||"").trim();if(!e||!t)return null;const o=(e.split("_")[0]||"").trim(),n=jt(t);if(!o||!n||!u(n))return null;let c=[];try{c=$(n,{withFileTypes:!0})}catch{c=[]}let l=null;for(const r of c){if(!r?.isDirectory?.())continue;const i=String(r.name||"");if(!(i===e||i===o||i.startsWith(`${e}_`)||i.startsWith(`${o}_`)))continue;const d=a(n,i),p=vt(d);p&&(!l||Number(p.mtime||0)>Number(l.mtime||0))&&(l=p)}return l}catch{return null}}g.get("/api/config/check",(s,t)=>{const e=rt();t.json({exists:u(e),path:e,isProjectLevel:e.startsWith(I)})}),g.get("/api/projects",(s,t)=>{try{const e=a(v,".zibby","config.json");if(!u(e))return t.json({projects:[]});const o=JSON.parse(_(e,"utf8")),n=typeof o.sessionToken=="string"&&o.sessionToken.trim()!==""?o.sessionToken.trim():"",c=Array.isArray(o.projects)?o.projects:[];if(!n)return t.json({projects:c});const l=String(wt()).replace(/\/$/,"");fetch(`${l}/projects`,{headers:{Authorization:`Bearer ${n}`}}).then(r=>r.json().catch(()=>({})).then(i=>({ok:r.ok,status:r.status,body:i}))).then(({ok:r,body:i})=>{if(!r)return t.json({projects:c});const p=(Array.isArray(i?.projects)?i.projects:[]).map(m=>({name:m?.name,projectId:m?.projectId,apiToken:m?.apiToken||null,createdAt:m?.createdAt||null,updatedAt:m?.updatedAt||null}));o.projects=p;try{H(e,`${JSON.stringify(o,null,2)}
|
|
9
9
|
`,"utf8")}catch{}return t.json({projects:p})}).catch(()=>t.json({projects:c}))}catch(e){t.status(500).json({error:e.message})}}),g.post("/api/projects/create",async(s,t)=>{try{const e=typeof s.body?.name=="string"?s.body.name.trim():"";if(!e)return t.status(400).json({error:"Project name is required"});const o=a(v,".zibby","config.json");if(!u(o))return t.status(401).json({error:"Not logged in"});const n=JSON.parse(_(o,"utf8")),c=typeof n.sessionToken=="string"&&n.sessionToken.trim()!==""?n.sessionToken.trim():"";if(!c)return t.status(401).json({error:"Not logged in"});const l=String(wt()).replace(/\/$/,""),r=await fetch(`${l}/projects`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({name:e})}),i=await r.json().catch(()=>({}));if(!r.ok)return t.status(r.status).json({error:i.error||i.message||`HTTP ${r.status}`});const d=i?.project&&typeof i.project=="object"?i.project:null;if(d?.projectId){const m=(Array.isArray(n.projects)?n.projects:[]).filter(w=>String(w?.projectId||"")!==String(d.projectId));m.push({name:d.name||e,projectId:d.projectId,apiToken:d.apiToken||i?.apiToken||null,createdAt:d.createdAt||null,updatedAt:d.updatedAt||null}),n.projects=m;try{H(o,`${JSON.stringify(n,null,2)}
|
|
10
10
|
`,"utf8")}catch{}}return t.json(i)}catch(e){return t.status(500).json({error:e.message||String(e)})}});function $t(s,t){const e=Array.isArray(t)?t.filter(d=>typeof d=="string"):[],o=process.argv[1]?O(process.argv[1]):"",n=o?Qt(o):"";let c;try{c=!!o&&u(o)&&L(o).isFile()&&!/\.(cmd|ps1|bat)$/i.test(o)&&(/\.(m|c)?js$/i.test(o)||n==="zibby")}catch{c=!1}if(c){const d=[o,"test",s,...e],p=[process.execPath,...d].map(m=>/\s/.test(String(m))?`"${String(m).replace(/"/g,'\\"')}"`:m).join(" ");return{useShell:!1,cmd:process.execPath,args:d,display:p}}const l=s.replace(/"/g,'\\"'),r=e.join(" "),i=`zibby test "${l}" ${r}`.trim();return{useShell:!0,cmd:i,args:[],display:i}}g.get("/api/run/result/:sessionId",(s,t)=>{const{sessionId:e}=s.params,o=D.get(e);if(!o)return t.status(404).json({pending:!0,error:"unknown_session"});t.json(o)}),g.post("/api/run",async(s,t)=>{const{task:e,args:o=[],sessionId:n,studioTestCaseId:c}=s.body;if(!e||!n)return t.status(400).json({success:!1,error:"task and sessionId are required"});const l=x(),r=a(l,n),i=O(r),d=c!=null&&String(c).trim()!==""?String(c).trim():String(n);D.set(n,{pending:!0});let p=!1,m=null;const w=()=>{if(m&&!m.destroyed)try{m.end()}catch{}m=null},M=(f,S)=>{D.delete(n),w(),p||t.status(f).json(S)},h=()=>{const f=[];return k.clients.forEach(S=>{S.sessionId===n&&f.push(S)}),f};try{const f=$t(e,o);console.log("[Studio API] Running:",f.display),f.useShell?console.warn('[Studio API] Falling back to shell "zibby" from PATH \u2014 if runs do nothing, run Studio from this repo or ensure `zibby` points to the same install.'):console.log("[Studio API] Using same CLI as this server (argv[1]):",process.argv[1]),bt(r,{recursive:!0}),m=Yt(a(r,nt),{flags:"w"}),B(i,{sessionId:String(n),studioTestCaseId:d,status:"running",runSource:"studio",activeStageIndex:0,activeNode:"preflight",cwd:I,outputBase:".zibby/output",sessionPathAbs:i});const S=st(f.cmd,f.args,{cwd:I,shell:f.useShell,env:{...process.env,ZIBBY_SESSION_ID:n,ZIBBY_SESSION_PATH:O(r)}});R.set(n,S),Rt(r,n,S.pid),B(i,{sessionId:String(n),studioTestCaseId:d,status:"running",runSource:"studio",activeStageIndex:0,activeNode:"preflight",cwd:I,outputBase:".zibby/output",sessionPathAbs:i,pid:S.pid??null});let T="",F="",dt=!1,ft=0;const pt=setInterval(()=>{try{const b=Pt(r);if(!b||b.mtime<=ft)return;ft=b.mtime;const j=_(b.p).toString("base64"),P=b.p.toLowerCase().endsWith(".png")?"image/png":"image/jpeg";h().forEach(K=>{try{K.send(JSON.stringify({type:"video-frame",sessionId:n,frame:j,mime:P}))}catch{}})}catch{}},320),mt=b=>{if(dt)return;dt=!0,w();const j={pending:!1,...b};typeof j.stdout=="string"&&j.stdout.length>G&&(j.stdout=`\u2026(truncated)
|
|
11
11
|
${j.stdout.slice(-G)}`),typeof j.stderr=="string"&&j.stderr.length>G&&(j.stderr=`\u2026(truncated)
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1029.0",
|
|
36
|
-
"@zibby/core": "^0.1.
|
|
36
|
+
"@zibby/core": "^0.1.25",
|
|
37
37
|
"@zibby/memory": "^0.1.4",
|
|
38
|
-
"@zibby/skills": "^0.1.
|
|
38
|
+
"@zibby/skills": "^0.1.5",
|
|
39
39
|
"adm-zip": "^0.5.17",
|
|
40
40
|
"chalk": "^5.3.0",
|
|
41
41
|
"commander": "^12.0.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import i from"os";import a from"path";import{existsSync as m,readFileSync as S,readdirSync as h,createWriteStream as g,mkdirSync as x,rmSync as I,unlinkSync as Z}from"fs";import{execFileSync as b}from"child_process";import{createInterface as v}from"readline";import l from"chalk";const A=process.env.ZIBBY_STUDIO_CDN||"https://dl.zibby.app",n=a.join(i.homedir(),".zibby","studio");function w(){const t=i.platform(),o=i.arch();if(t==="darwin"&&o==="arm64")return{archive:"Zibby Studio-mac-arm64.zip",label:"macOS (Apple Silicon)"};if(t==="darwin")return{archive:"Zibby Studio-mac-x64.zip",label:"macOS (Intel)"};if(t==="win32"&&o==="arm64")return{archive:"Zibby Studio-win-arm64.zip",label:"Windows (ARM)"};if(t==="win32")return{archive:"Zibby Studio-win-x64.zip",label:"Windows (x64)"};if(t==="linux"&&o==="arm64")return{archive:"Zibby Studio-arm64.AppImage",label:"Linux (ARM64)"};if(t==="linux")return{archive:"Zibby Studio-1.0.0.AppImage",label:"Linux (x64)"};throw new Error(`Unsupported platform: ${t} ${o}`)}function $(){const{archive:t}=w();return`${A}/download/latest/${encodeURIComponent(t)}`}function z(t){const o=v({input:process.stdin,output:process.stdout});return new Promise(e=>{o.question(t,u=>{o.close(),e(u.trim().toLowerCase())})})}async function C(){const{label:t}=w();console.log(""),console.log(l.cyan(" Zibby Studio is not installed.")),console.log(l.gray(` Platform: ${t}`)),console.log("");const o=await z(l.white(" Download and install Zibby Studio? (Y/n): "));return o&&o!=="y"&&o!=="yes"?(console.log(l.yellow(`
|
|
2
2
|
Skipped.
|
|
3
3
|
`)),!1):(await D(),!0)}async function D(){const t=$(),o=decodeURIComponent(a.basename(t));console.log(l.cyan(`
|
|
4
|
-
\u{1F4E6} Downloading Zibby Studio...`));try{const e=await fetch(t);if(!e.ok)throw new Error(`Download failed: ${e.status} ${e.statusText}`);const u=parseInt(e.headers.get("content-length")||"0",10),c=a.join(i.tmpdir(),o);let f=0;const
|
|
4
|
+
\u{1F4E6} Downloading Zibby Studio...`));try{const e=await fetch(t);if(!e.ok)throw new Error(`Download failed: ${e.status} ${e.statusText}`);const u=parseInt(e.headers.get("content-length")||"0",10),c=a.join(i.tmpdir(),o);let f=0;const d=g(c);for await(const r of e.body)if(f+=r.length,d.write(r),u>0){const s=(f/u*100).toFixed(1),p=(f/1024/1024).toFixed(1),y=(u/1024/1024).toFixed(1);process.stdout.write(`\r \u{1F4E5} ${s}% (${p}MB / ${y}MB)`)}if(await new Promise((r,s)=>{d.on("finish",r),d.on("error",s),d.end()}),console.log(""),m(n)&&I(n,{recursive:!0,force:!0}),x(n,{recursive:!0}),console.log(l.cyan(" \u{1F4C2} Installing...")),c.endsWith(".zip"))if(i.platform()==="darwin"||i.platform()==="linux"){if(b("unzip",["-oq",c,"-d",n]),i.platform()==="darwin")try{b("xattr",["-cr",n])}catch{}}else{const r=(await import("adm-zip")).default;new r(c).extractAllTo(n,!0)}else if(c.endsWith(".AppImage")){const{copyFileSync:r,chmodSync:s}=await import("fs"),p=a.join(n,o);r(c,p),s(p,493)}try{Z(c)}catch{}return console.log(l.green(` \u2705 Zibby Studio installed!
|
|
5
5
|
`)),!0}catch(e){throw console.log(l.red(`
|
|
6
6
|
\u274C Installation failed: ${e.message}
|
|
7
7
|
`)),e}}function M(){const t=k();return!!(t&&m(t))}function k(){if(i.platform()==="darwin")return a.join(n,"Zibby Studio.app");if(i.platform()==="win32")return a.join(n,"Zibby Studio.exe");if(i.platform()==="linux"){if(!m(n))return null;const t=h(n).find(o=>o.endsWith(".AppImage"));return t?a.join(n,t):null}return null}function O(){const t=a.join(n,"version.txt");return m(t)?S(t,"utf-8").trim():"unknown"}export{k as getStudioAppPath,O as getStudioVersion,D as installStudio,M as isStudioInstalled,C as promptAndInstallStudio};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as d,execFileSync as s}from"child_process";import c from"os";import a from"path";import{existsSync as l,mkdirSync as f,writeFileSync as m}from"fs";import{getStudioAppPath as S}from"./studio-installer.js";const p=a.join(c.homedir(),".zibby","studio-launch.json");function h(r){const o={};r.projectRoot&&(o.projectRoot=r.projectRoot),r.port&&(o.port=r.port),o.launchedAt=Date.now();const i=a.dirname(p);f(i,{recursive:!0}),m(p,JSON.stringify(o,null,2))}function w(r){if(c.platform()==="darwin"){try{s("xattr",["-cr",r])}catch{}try{s("spctl",["--add","--label","ZibbyStudio",r])}catch{}}}function u(r,o){return new Promise(i=>{const t=d("open",["-a",r,"--env",`ZIBBY_STUDIO_PROJECT_ROOT=${o.projectRoot}`],{stdio:["ignore","pipe","pipe"]});let e="";t.stderr?.on("data",n=>{e+=n.toString()}),t.on("close",n=>i({code:n,stderr:e})),t.on("error",n=>i({code:1,stderr:n.message}))})}async function j(r={}){const o=S();if(!o)throw new Error("Studio not installed");if(!l(o))throw new Error(`Studio app not found at ${o}`);h(r);const i=r.projectRoot||process.cwd();if(c.platform()==="darwin"){let t=await u(o,{projectRoot:i});if(t.code!==0&&t.stderr.includes("Launch failed")&&(w(o),t=await u(o,{projectRoot:i})),t.code!==0){const e=t.stderr.trim();e&&console.error(`[Studio Desktop] ${e}`),console.error(`Zibby Studio exited with code ${t.code}`)}}else{const t=d(o,[],{detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,ZIBBY_STUDIO_PROJECT_ROOT:i}});t.unref(),t.stderr?.on("data",e=>{const n=e.toString().trim();n&&console.error(`[Studio Desktop] ${n}`)}),t.on("error",e=>{console.error(`Failed to open Zibby Studio: ${e.message}`)})}}export{j as launchStudio};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1029.0",
|
|
36
|
-
"@zibby/core": "^0.1.
|
|
36
|
+
"@zibby/core": "^0.1.25",
|
|
37
37
|
"@zibby/memory": "^0.1.4",
|
|
38
|
-
"@zibby/skills": "^0.1.
|
|
38
|
+
"@zibby/skills": "^0.1.5",
|
|
39
39
|
"adm-zip": "^0.5.17",
|
|
40
40
|
"chalk": "^5.3.0",
|
|
41
41
|
"commander": "^12.0.0",
|