@zibby/cli 0.4.3 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/zibby.js +3 -3
- package/dist/commands/init.js +72 -72
- package/dist/commands/workflows/deploy-helpers.js +3 -1
- package/dist/commands/workflows/deploy.js +41 -39
- package/dist/commands/workflows/generate.js +21 -21
- package/dist/commands/workflows/run-helpers.js +2 -2
- package/dist/commands/workflows/run-local.js +19 -19
- package/dist/commands/workflows/run.js +5 -5
- package/dist/commands/workflows/trigger.js +61 -20
- package/dist/package.json +3 -3
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{mkdirSync as
|
|
3
|
-
`)}import"@zibby/core";var P=process.env.WORKSPACE||"/workspace";async function
|
|
4
|
-
Workflow execution failed: ${
|
|
5
|
-
[done] ${
|
|
6
|
-
[done] ${
|
|
2
|
+
import{mkdirSync as z,writeFileSync as te,existsSync as w,readFileSync as G}from"fs";import{join as g,dirname as ne,resolve as K}from"path";import{pathToFileURL as I}from"url";import{execSync as se,spawn as W}from"node:child_process";import{SQSClient as X,SendMessageCommand as Z}from"@aws-sdk/client-sqs";var b=null;function V(){return b||(b=new X({region:process.env.AWS_REGION||"ap-southeast-2"})),b}async function L(n,{status:e,error:o}){let{EXECUTION_ID:s,SQS_AUTH_TOKEN:a,PROGRESS_API_URL:i,PROGRESS_QUEUE_URL:t,PROJECT_API_TOKEN:f}=n;if(!s)return;let c={executionId:s,...a&&{sqsAuthToken:a},status:e,...o&&{error:o},timestamp:new Date().toISOString()},l=i?"HTTP":t?"SQS":"NONE",u=JSON.stringify(c).length;console.log(`Sending final status: ${e} via ${l} (${(u/1024).toFixed(1)}KB)`);try{if(i)await ee(i,s,c,f);else if(t){let d=["completed","failed","insufficient_context","blocked"].includes(e)?"execution_completed":"progress_update";await oe(t,s,c,d)}else{console.warn("No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`Final status ${e} sent via ${l}`)}catch(d){console.error(`Failed to send final status (${e}) via ${l}:`),console.error(` Payload: ${(u/1024).toFixed(1)}KB`),console.error(` Error: ${d.message}`),d.name&&console.error(` Error type: ${d.name}`),d.code&&console.error(` Error code: ${d.code}`)}}async function ee(n,e,o,s){let a=`${n}/${e}/progress`,i={"Content-Type":"application/json"};s&&(i.Authorization=`Bearer ${s}`);let t=await fetch(a,{method:"POST",headers:i,body:JSON.stringify(o)});if(!t.ok){let f=await t.text();throw new Error(`HTTP ${t.status}: ${f}`)}}async function oe(n,e,o,s="progress_update"){let a=JSON.stringify(o),i=(a.length/1024).toFixed(1);a.length>256*1024&&console.error(`\u274C SQS message too large: ${i}KB (limit 256KB) for ${e} [${s}]`),await V().send(new Z({QueueUrl:n,MessageBody:a,MessageGroupId:e,MessageAttributes:{executionId:{DataType:"String",StringValue:e},messageType:{DataType:"String",StringValue:s}}}))}function D({workflowType:n,jobId:e,projectId:o,agentType:s,model:a,egressIp:i,egressKind:t}){let f="\u2500".repeat(60),c=`${s||"default"} (model: ${a||"auto"})`,l=["",f,` Workflow: ${n}`,` Job: ${e||"local"}`,` Project: ${o||"none"}`,` Agent: ${c}`];if(i||t){let u=i||"unknown",d=t||"static";l.push(` Egress: ${u} (${d})`)}return l.push(f),l.join(`
|
|
3
|
+
`)}import"@zibby/core";var P=process.env.WORKSPACE||"/workspace";async function re(n,e){z(e,{recursive:!0});let o=Date.now();console.log("[setup] Fetching bundle...");let s=setInterval(()=>{let i=((Date.now()-o)/1e3).toFixed(1);console.log(`[setup] still fetching (${i}s elapsed)`)},3e3);try{await new Promise((i,t)=>{let f=W("curl",["-fsSL",n],{stdio:["ignore","pipe","inherit"]}),c=W("tar",["-xzf","-","-C",e],{stdio:["pipe","inherit","inherit"]});f.stdout.pipe(c.stdin);let l,u,d=()=>{if(l!==void 0&&u!==void 0){if(l!==0)return t(new Error(`curl exited ${l}`));if(u!==0)return t(new Error(`tar exited ${u}`));i()}};f.on("close",S=>{l=S,d()}),c.on("close",S=>{u=S,d()}),f.on("error",t),c.on("error",t)})}finally{clearInterval(s)}let a=((Date.now()-o)/1e3).toFixed(1);return console.log(`[setup] Bundle extracted (${a}s)`),e}async function j(){let n=process.env.WORKFLOW_SOURCES_URL;if(!n)throw new Error("WORKFLOW_SOURCES_URL env var is required");let e=await fetch(n);if(!e.ok)throw new Error(`Failed to fetch sources: ${e.status} ${e.statusText}`);let o=await e.json();if(!o.sources||typeof o.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return o}function ie(n){let e=n?.agent;if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(typeof e.provider=="string")return e.provider;for(let o of["claude","cursor","codex","gemini"])if(e[o])return o}return null}function ae(n,e){let o=K(e),s=0;for(let[a,i]of Object.entries(n)){let t=K(e,a);if(!t.startsWith(`${o}/`)&&t!==o){console.error(` \u26D4 Skipping unsafe path: ${a}`);continue}z(ne(t),{recursive:!0}),te(t,i,"utf-8"),s++}return s}async function ce(){let n=process.env.ZIBBY_EGRESS_PROXY_URL,e=process.env.ZIBBY_EGRESS_TOKEN;if(!(!n||!e))try{let o=await import("undici"),s=new o.ProxyAgent({uri:n,token:`Bearer ${e}`});o.setGlobalDispatcher(s)}catch(o){console.warn(`[setup] Failed to install egress proxy dispatcher: ${o.message}`)}}async function le(){if(process.env.ZIBBY_EGRESS_IP)return{ip:process.env.ZIBBY_EGRESS_IP,kind:"static"};try{let n=new AbortController,e=setTimeout(()=>n.abort(),1500),o=await fetch("https://api.ipify.org?format=json",{signal:n.signal});return clearTimeout(e),o.ok?{ip:(await o.json())?.ip||null,kind:"dynamic"}:{ip:null,kind:"dynamic"}}catch{return{ip:null,kind:"dynamic"}}}async function de(n,e){let o=g(n,"graph.mjs");if(!w(o))throw new Error(`graph.mjs not found at ${o}`);let s=await import(I(o).href),a=e?.entryClass,i=a&&s[a]||s.default||Object.values(s).find(t=>typeof t=="function"&&t.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs");return i}async function he(){if(!process.env.NODE_PATH){process.env.NODE_PATH="/opt/zibby/packages";let r=await import("module");r.default._initPaths&&r.default._initPaths()}await ce();let{WORKFLOW_JOB_ID:n,WORKFLOW_TYPE:e,PROJECT_ID:o,AGENT_TYPE:s,MODEL:a}=process.env;e||(console.error("Missing WORKFLOW_TYPE env var"),process.exit(1));let i=process.env.WORKFLOW_BUNDLE_URL,t,f={},c,l;if(i){c=e,t=g(P,".zibby","workflows",c);try{await re(i,t);try{let r=await j();f=r.input||{},l=r.version}catch{}}catch(r){console.warn(`[setup] Bundle extract failed (${r.message}); falling back to source install`),t=null}}if(!t){let r=await j(),{sources:p,input:m,workflowType:_,version:E}=r;f=m||{},c=_||e,l=E,console.log(`[setup] Workflow v${l||"?"} (${Object.keys(p).length} files)`),t=g(P,".zibby","workflows",c);let R=ae(p,t);console.log(`[setup] Wrote ${R} files`),console.log("[setup] Installing dependencies...");try{se("npm install --silent --no-audit --no-fund",{cwd:t,stdio:"inherit"}),console.log("[setup] Dependencies installed")}catch(h){console.warn(`[setup] npm install failed: ${h.message}`)}}let u={},d=g(t,"workflow.json");w(d)&&(u=JSON.parse(G(d,"utf-8")));let S={},U=g(t,"zibby.config.json");if(w(U))try{S=JSON.parse(G(U,"utf-8")),console.log("[setup] Loaded user config from zibby.config.json")}catch(r){console.warn(`[setup] Failed to parse zibby.config.json: ${r.message} \u2014 falling back to defaults`)}let Q=ie(S)||s,k=await le();console.log(D({workflowType:e,jobId:n,projectId:o,agentType:Q,model:a,egressIp:k.ip,egressKind:k.kind}));let x=await de(t,u);console.log(`[setup] Loaded ${x.name}`);let y=[],A=g(t,"node_modules","@zibby","agent-workflow"),v=g(t,"node_modules","@zibby","core","node_modules","@zibby","agent-workflow");w(A)&&y.push({kind:"hoisted",path:A}),w(v)&&y.push({kind:"nested",path:v});let O=process.env.ZIBBY_RUN_DIAG==="1";if(O){let{readdirSync:r}=await import("fs");console.log(` [diag] @zibby/agent-workflow copies in bundle: ${y.length}`);for(let p of y)console.log(` [diag] ${p.kind}: ${p.path}`);try{let p=g(t,"node_modules","@zibby");w(p)&&console.log(` [diag] node_modules/@zibby/ contents: [${r(p).join(", ")}]`)}catch{}}let C=g(t,"node_modules","@zibby","core","dist","index.js");if(w(C)&&y.length>0)try{let r=await import(I(C).href),p=[r.AssistantStrategy,r.CursorAgentStrategy,r.ClaudeAgentStrategy,r.CodexAgentStrategy,r.GeminiAgentStrategy].filter(Boolean);for(let m of y){let _=g(m.path,"dist","index.js");if(!w(_))continue;let E=await import(I(_).href),R=O?E.listStrategies():null;for(let h of p)try{E.registerStrategy(new h)}catch(q){console.warn(` register ${h.name} into ${m.kind} failed: ${q.message}`)}O&&console.log(` [diag] ${m.kind} registry: before=[${R.join(",")||"empty"}] after=[${E.listStrategies().join(",")||"empty"}]`)}console.log("[setup] Registered 5 agent strategies (assistant, cursor, claude, codex, gemini)")}catch(r){console.warn(`[setup] Failed to bridge strategies: ${r.message}`)}else console.warn("[setup] No @zibby/core or @zibby/agent-workflow in bundle \u2014 agent strategies may be unavailable");let J=Date.now(),N=new x({workflow:c||e}),H=N.buildGraph(),M={input:f||{},cwd:P,runId:n||`run-${Date.now()}`,config:S};console.log("");let $;try{$=await H.run(N,M)}catch(r){console.error(`
|
|
4
|
+
Workflow execution failed: ${r.message}`),console.error(r.stack),await T("failed",r.message),process.exit(1)}let B=((Date.now()-J)/1e3).toFixed(1),Y=$?.success!==!1,F=c||e;Y?(console.log(`
|
|
5
|
+
[done] ${F} completed in ${B}s`),await T("completed")):(console.error(`
|
|
6
|
+
[done] ${F} failed after ${B}s`),await T("failed",$?.error||"Workflow execution failed"),process.exit(1))}async function T(n,e=null){let o={EXECUTION_ID:process.env.WORKFLOW_JOB_ID,PROGRESS_API_URL:process.env.PROGRESS_API_URL,PROGRESS_QUEUE_URL:process.env.PROGRESS_QUEUE_URL,PROJECT_API_TOKEN:process.env.PROJECT_API_TOKEN,SQS_AUTH_TOKEN:process.env.SQS_AUTH_TOKEN};if(o.EXECUTION_ID)try{await L(o,{status:n,...e&&{error:e}})}catch(s){console.error(`\u26A0\uFE0F Failed to report status: ${s.message}`)}}export{ie as resolveAgentFromConfig,he as runWorkflowCommand};
|
|
@@ -1,22 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
`),process.exit(1));try{
|
|
4
|
-
|
|
5
|
-
`),process.exit(1)}
|
|
6
|
-
|
|
7
|
-
`),process.exit(1)
|
|
1
|
+
var F=Object.defineProperty;var J=(e,o)=>()=>(e&&(o=e(e=0)),o);var Y=(e,o)=>{for(var t in o)F(e,t,{get:o[t],enumerable:!0})};var O={};Y(O,{logsCommand:()=>le,parseSseChunk:()=>P,runReconnectLoop:()=>B,sseBackoffMs:()=>A});import i from"chalk";import{readFileSync as K,existsSync as q,writeSync as H}from"fs";import{homedir as X}from"os";import{join as Q}from"path";async function oe(e){return $||(process.env.ZIBBY_SSE_ENDPOINT?($=process.env.ZIBBY_SSE_ENDPOINT,$):($=ee,$))}function te(e){let o=Q(X(),".zibby","config.json");q(o)||(console.log(i.red(`
|
|
2
|
+
Not authenticated`)),console.log(i.gray(` Run: zibby login
|
|
3
|
+
`)),process.exit(1));let t;try{t=JSON.parse(K(o,"utf-8"))}catch{console.log(i.red(`
|
|
4
|
+
Config file corrupt`)),console.log(i.gray(` Run: zibby login
|
|
5
|
+
`)),process.exit(1)}let n=t.sessionToken;n||(console.log(i.red(`
|
|
6
|
+
Not authenticated`)),console.log(i.gray(` Run: zibby login
|
|
7
|
+
`)),process.exit(1));let s=e.project;return{token:n,projectId:s}}function v(e){return new Date(e).toISOString().replace("T"," ").replace("Z","")}async function R(e,o){let t=await fetch(e,{headers:{Authorization:`Bearer ${o}`}});if(!t.ok){let n=await t.text();throw new Error(`API ${t.status}: ${n}`)}return t.json()}async function ne(e,o,t,n){return e||(console.log(i.red(`
|
|
8
|
+
Workflow UUID is required`)),console.log(i.gray(" Usage: zibby workflow logs <workflow-uuid>")),console.log(i.gray(` zibby workflow logs <workflow-uuid> -t
|
|
9
|
+
`)),process.exit(1)),e}function P(e,o){let n=((e||"")+o).split(`
|
|
10
|
+
`),s=n.pop()||"",l=[],a=null,r=null;for(let c=0;c<n.length;c++){let f=n[c];if(f.trim()){if(f.startsWith("id:")){a=f.slice(3).trim();continue}if(f.startsWith("event:")){let g=f.slice(6).trim();if(g==="log")continue;if(g==="status"){let u=n[c+1];if(u&&u.startsWith("data:"))try{let d=JSON.parse(u.slice(5).trim());d.status==="new_execution"?l.push({type:"newExecution",executionId:d.executionId,taskId:d.taskId}):d.status==="waiting"&&l.push({type:"waiting"})}catch{}continue}if(g==="complete"){l.push({type:"complete"});continue}if(g==="error"){let u=n[c+1];if(u&&u.startsWith("data:"))try{if(JSON.parse(u.slice(5).trim()).error==="No executions found for workflow"){r={type:"notFound"};break}}catch{}r={type:"failed"};break}continue}if(f.startsWith("data:")){let g=f.slice(5).trim();if(!g)continue;try{let u=JSON.parse(g);u.timestamp&&u.message&&l.push({type:"log",timestamp:u.timestamp,message:u.message,taskId:u.taskId})}catch{}}}}return{actions:l,remainder:s,lastEventId:a,returnSignal:r}}async function re({token:e,executionId:o,sseEndpoint:t,stopped:n}){let s=null;try{let l=new URL(t);l.searchParams.set("jobId",o),s&&l.searchParams.set("lastEventId",s);let a=await fetch(l.toString(),{headers:{Authorization:`Bearer ${e}`,Accept:"text/event-stream"}});if(!a.ok)throw new Error(`SSE connection failed: ${a.status} ${a.statusText}`);let r=a.body.getReader(),c=new TextDecoder,f="",g=!1;for(;!n.value;){let{done:u,value:d}=await r.read();if(u)break;let y=P(f,c.decode(d,{stream:!0}));f=y.remainder,y.lastEventId&&(s=y.lastEventId);for(let p of y.actions)switch(p.type){case"newExecution":{let m=`${p.executionId.slice(0,8)}...${p.executionId.slice(-4)}`,h=p.taskId?p.taskId.slice(-8):"pending";console.log(i.cyan(`
|
|
11
|
+
\u250C\u2500 Execution: ${m} (task: ${h})`)),console.log(i.cyan(` \u2514\u2500 Streaming logs...
|
|
12
|
+
`));break}case"waiting":console.log(i.gray(`
|
|
13
|
+
Waiting for next execution...`));break;case"complete":g=!0;break;case"log":{let m=i.gray(v(p.timestamp)),h=p.taskId?i.gray(`(${p.taskId.slice(-8)}) `):"";console.log(`${m} ${h}${p.message.replace(/\n$/,"")}`);break}}if(y.returnSignal)return y.returnSignal.type==="notFound"?{notFound:!0}:{failed:!0}}return{completed:g}}catch(l){if(l.name==="AbortError")return{aborted:!0};throw l}}function A(e,{baseMs:o=500,capMs:t=3e4,rand:n=Math.random}={}){let s=Math.min(t,o*Math.pow(2,Math.max(0,e)));return Math.floor(n()*s)}async function B({attemptStream:e,stopped:o,follow:t,logger:n,sleep:s=c=>new Promise(f=>setTimeout(f,c)),exit:l=c=>{throw new Error(`exit:${c}`)},backoff:a=A,notFoundPollMs:r=5e3}){let c=0,f=!1;for(;!o.value;){let g;try{g=await e(),c=0}catch(u){if(u.name==="AbortError"||o.value)return{reason:"aborted"};if(f||(n.error(` SSE Error: ${u.message}`),t&&n.gray(" Reconnecting..."),f=!0),!t)return l("error")??{reason:"error"};let d=a(c);c++,await s(d);continue}if(g.aborted||o.value)return{reason:"aborted"};if(g.notFound){if(t){f||(n.yellow(" No executions found yet. Waiting for workflow to be triggered..."),n.gray(" Press Ctrl+C to stop."),f=!0),await s(r);continue}return n.yellow(`
|
|
14
|
+
No executions found for this workflow. Trigger the workflow first.
|
|
15
|
+
`),l("notFound")??{reason:"notFound"}}if(f&&(n.gray(` Reconnected.
|
|
16
|
+
`),f=!1),g.failed)return n.red(`
|
|
17
|
+
Execution failed.`),t?{reason:"failed"}:l("failed")??{reason:"failed"};if(g.completed)return l("completed")??{reason:"completed"};if(!t)return{reason:"disconnected"}}return{reason:"stopped"}}async function se({token:e,jobId:o,follow:t,projectId:n}){console.log(i.gray(` Streaming logs for workflow ${i.cyan(o)}...`)),console.log(t?i.gray(` Press Ctrl+C to stop.
|
|
18
|
+
`):"");let s=await oe(e);if(!s)return console.log(i.yellow(` SSE endpoint not configured, using CloudWatch polling...
|
|
19
|
+
`)),C({token:e,projectId:null,jobId:o,follow:t,limit:1e5});let l={value:!1},a=()=>{l.value=!0;try{H(2,`
|
|
20
|
+
Stopped streaming.
|
|
21
|
+
`)}catch{}process.exit(0)};process.prependListener("SIGINT",a),process.prependListener("SIGTERM",a),await B({attemptStream:()=>re({token:e,executionId:o,sseEndpoint:s,stopped:l}),stopped:l,follow:t,logger:{gray:r=>console.log(i.gray(r)),red:r=>console.log(i.red(r)),yellow:r=>console.log(i.yellow(r)),error:r=>console.error(i.red(r))},exit:r=>{r==="completed"&&process.exit(0),(r==="error"||r==="notFound"||r==="failed")&&process.exit(1)}})}async function C({token:e,projectId:o,jobId:t,follow:n,limit:s}){let l=o?`${S}/logs/${o}/${t}`:`${S}/job/${t}`,a=null,r=0,c=new Set,f=!1,g=0,u=5,d=()=>{f=!0,console.log(i.gray(`
|
|
22
|
+
Stopped tailing.
|
|
23
|
+
`)),process.exit(0)};for(process.on("SIGINT",d),process.on("SIGTERM",d),console.log(i.gray(` Fetching logs for workflow ${i.cyan(t)}...`)),console.log(n?i.gray(` Press Ctrl+C to stop.
|
|
24
|
+
`):"");!f;)try{let y=new URLSearchParams({limit:String(s)});a&&y.set("nextToken",a);let p=await R(`${l}?${y}`,e);g=0,p.message&&p.lines?.length===0&&r===0&&console.log(i.gray(` ${p.message}`)),p.status==="starting"&&p.lines?.length===0&&r===0&&console.log(i.gray(" Container starting..."));for(let w of p.lines||[]){let I=`${w.timestamp}:${w.message}`;if(c.has(I))continue;c.add(I);let E=i.gray(v(w.timestamp)),D=p.taskId?i.gray(`(${p.taskId.slice(-8)}) `):"";console.log(`${E} ${D}${w.message.replace(/\n$/,"")}`)}if(r=p.lines?.length>0?0:r+1,a=p.nextForwardToken||null,p.status==="completed"||p.status==="failed"){let w=p.status==="completed"?i.green:i.red;console.log(w(`
|
|
25
|
+
Job ${p.status}.`)),process.exit(p.status==="completed"?0:1)}if(!n){p.status&&console.log(i.gray(`
|
|
26
|
+
Status: ${p.status}`));break}let x=p.lines?.length>0?500:r>5?5e3:2e3;await new Promise(w=>setTimeout(w,x))}catch(y){if(y.name==="AbortError")break;y.message.match(/API (400|401|403|404):/)&&(console.error(i.red(`
|
|
27
|
+
${y.message}
|
|
28
|
+
`)),process.exit(1)),g++,console.error(i.red(` Error: ${y.message}`)),g>=u&&(console.error(i.red(`
|
|
29
|
+
Too many consecutive errors (${u}). Stopping.
|
|
30
|
+
`)),process.exit(1)),n||process.exit(1),await new Promise(m=>setTimeout(m,3e3))}}async function ie({token:e,projectId:o,workflow:t,follow:n,limit:s}){let l=`${S}/all/${o}`,a=null,r=0,c=new Set,f=null,g=!1,u=0,d=5,y=()=>{g=!0,console.log(i.gray(`
|
|
31
|
+
Stopped tailing.
|
|
32
|
+
`)),process.exit(0)};for(process.on("SIGINT",y),process.on("SIGTERM",y),console.log(i.gray(`
|
|
33
|
+
Tailing all runs for ${i.cyan(t)}...`)),console.log(n?i.gray(` Press Ctrl+C to stop.
|
|
34
|
+
`):"");!g;)try{let p=new URLSearchParams({workflow:t,limit:String(s)});a&&p.set("nextToken",a);let m=await R(`${l}?${p}`,e);u=0,m.message&&m.lines?.length===0&&r===0&&console.log(i.gray(` ${m.message}`));for(let w of m.lines||[]){let I=`${w.timestamp}:${w.jobId}:${w.message}`;if(c.has(I))continue;c.add(I),w.jobId!==f&&(f!==null&&console.log(""),console.log(i.dim(` \u2500\u2500 ${w.jobId} \u2500\u2500`)),f=w.jobId);let E=i.gray(v(w.timestamp));console.log(`${E} ${w.message.replace(/\n$/,"")}`)}if(r=m.lines?.length>0?0:r+1,a=m.nextToken||null,!n){a&&console.log(i.gray(`
|
|
35
|
+
... more logs available. Run again or use --follow to stream.`)),m.jobCount&&console.log(i.gray(` ${m.jobCount} job(s) found.`));break}if(!m.hasRunning&&!a&&r>2){console.log(i.gray(`
|
|
36
|
+
No running jobs. All caught up.`));break}let x=m.lines?.length>0?500:r>5?5e3:2e3;await new Promise(w=>setTimeout(w,x))}catch(p){if(p.name==="AbortError")break;p.message.match(/API (400|401|403|404):/)&&(console.error(i.red(`
|
|
37
|
+
${p.message}
|
|
38
|
+
`)),process.exit(1)),u++,console.error(i.red(` Error: ${p.message}`)),u>=d&&(console.error(i.red(`
|
|
39
|
+
Too many consecutive errors (${d}). Stopping.
|
|
40
|
+
`)),process.exit(1)),n||process.exit(1),await new Promise(h=>setTimeout(h,3e3))}}async function le(e,o){let{token:t,projectId:n}=te(o),s=o.follow===!0,l=o.lines?parseInt(o.lines,10):1e5;if(o.all){let r=o.workflow;return r||(console.log(i.red(`
|
|
41
|
+
--workflow is required with --all`)),console.log(i.gray(` Example: zibby workflow logs --workflow ticket-triage --all --project <id>
|
|
42
|
+
`)),process.exit(1)),ie({token:t,projectId:n,workflow:r,follow:s,limit:l})}let a=await ne(e,o,t,n);return s?se({token:t,jobId:a,follow:s,projectId:n}):C({token:t,projectId:n,jobId:a,follow:!1,limit:l})}var S,ee,$,z=J(()=>{S="https://logs.workflows.zibby.app",ee="https://logs-stream.zibby.app/",$=null});import T from"ora";import{select as L}from"@inquirer/prompts";import{readFileSync as ae,existsSync as ce}from"fs";import{homedir as fe}from"os";import{join as pe}from"path";var b={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.dev",description:"Production environment"}};function k(){let e;if(process.env.ZIBBY_API_URL)e=process.env.ZIBBY_API_URL;else{let o=process.env.ZIBBY_ENV||"prod";b[o]?e=b[o].apiUrl:e=b.prod.apiUrl}try{let o=new URL(e);return o.protocol!=="http:"&&o.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${o.protocol} (only http/https allowed)`),b.prod.apiUrl):e}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${e}`),b.prod.apiUrl}}var Z=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function U(e){return e?Z.test(e)?{ok:!0}:{ok:!1,error:`'${e}' is not a UUID. Cloud workflows are identified by UUID only. Run \`zibby workflow list\` to find yours, or run \`zibby workflow trigger\` with no argument for interactive selection.`}:{ok:!0}}import{existsSync as W,readFileSync as G}from"fs";import{resolve as M}from"path";function j(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}function _(e){let o={};for(let t of e||[]){let n=t.indexOf("=");if(n===-1){console.warn(` Warning: ignored param "${t}" \u2014 expected key=value format`);continue}let s=t.slice(0,n).trim(),l=j(t.slice(n+1)),a=s.split("."),r=o;for(let c=0;c<a.length-1;c++)(typeof r[a[c]]!="object"||r[a[c]]===null)&&(r[a[c]]={}),r=r[a[c]];r[a[a.length-1]]=l}return o}function V(e){let o=M(e);W(o)||(console.log(`
|
|
43
|
+
Error: --input-file not found: ${e}
|
|
44
|
+
`),process.exit(1));try{return JSON.parse(G(o,"utf-8"))}catch(t){console.log(`
|
|
45
|
+
Error: --input-file is not valid JSON: ${t.message}
|
|
46
|
+
`),process.exit(1)}}function N(e){let o={};if(e.inputFile&&(o={...V(e.inputFile)}),e.input)try{o={...o,...JSON.parse(e.input)}}catch(t){console.log(`
|
|
47
|
+
Error: --input is not valid JSON`),console.log(` ${t.message}
|
|
48
|
+
`),process.exit(1)}return e.param?.length&&(o={...o,..._(e.param)}),o}function ue(){let e=pe(fe(),".zibby","config.json");if(ce(e))try{let t=JSON.parse(ae(e,"utf-8"));if(t.sessionToken)return t.sessionToken}catch{}let o=process.env.ZIBBY_API_KEY;if(o)return o;console.log(`
|
|
8
49
|
Not authenticated`),console.log(" Run: zibby login"),console.log(` OR set ZIBBY_API_KEY env var (for CI/CD)
|
|
9
|
-
`),process.exit(1)}async function
|
|
10
|
-
Error: ${
|
|
11
|
-
`),process.exit(1));let
|
|
12
|
-
\u2713 Found workflow "${
|
|
13
|
-
`);break}}}(!
|
|
14
|
-
Error: Workflow with UUID "${
|
|
15
|
-
`),process.exit(1))}}catch(
|
|
16
|
-
Error looking up workflow UUID: ${
|
|
17
|
-
`),process.exit(1)}}
|
|
50
|
+
`),process.exit(1)}async function ge(e){let o=k(),t=T("Fetching projects...").start();try{let n=await fetch(`${o}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});n.ok||(t.fail("Failed to fetch projects"),process.exit(1));let s=await n.json();Array.isArray(s)||(s.projects?s=s.projects:s.data&&(s=s.data)),(!s||s.length===0)&&(t.fail("No projects found"),process.exit(1)),t.succeed(`Found ${s.length} project${s.length===1?"":"s"}`),console.log("");let l=s.map(a=>({name:`${a.name||"Unnamed"} (${a.projectId||a.id})`,value:a.projectId||a.id}));return await L({message:"Select a project:",choices:l})}catch(n){t.fail(`Error: ${n.message}`),process.exit(1)}}async function de(e,o){let t=k(),n=T("Fetching deployed workflows...").start();try{let s=["analysis","implementation","run_test"],l=[];for(let r of s){let c=await fetch(`${t}/projects/${e}/workflows/${r}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});if(c.ok){let f=await c.json();f.graph&&l.push({name:r,version:f.version||0,isDefault:f.isDefault!==!1})}}l.length===0&&(n.fail("No deployed workflows found for this project"),process.exit(1)),n.succeed(`Found ${l.length} deployed workflow${l.length===1?"":"s"}`),console.log("");let a=l.map(r=>({name:`${r.name} (v${r.version})${r.isDefault?" [default]":""}`,value:r.name}));return await L({message:"Select a workflow to trigger:",choices:a})}catch(s){n.fail(`Error: ${s.message}`),process.exit(1)}}async function Pe(e,o={}){let t=U(e);t.ok||(console.log(`
|
|
51
|
+
Error: ${t.error}
|
|
52
|
+
`),process.exit(1));let n=ue(),s=o.project||process.env.ZIBBY_PROJECT_ID,l;if(e){let c=k();try{let f=await fetch(`${c}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});if(f.ok){let u=(await f.json()).projects||[];for(let d of u){let y=await fetch(`${c}/projects/${d.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});if(y.ok){let m=(await y.json()).find(h=>h.uuid===e);if(m){s=d.projectId,l=m.workflowType||m.name,console.log(`
|
|
53
|
+
\u2713 Found workflow "${l}" (UUID: ${e})
|
|
54
|
+
`);break}}}(!l||l===e)&&(console.log(`
|
|
55
|
+
Error: Workflow with UUID "${e}" not found`),console.log(` Check: zibby workflow list
|
|
56
|
+
`),process.exit(1))}}catch(f){console.log(`
|
|
57
|
+
Error looking up workflow UUID: ${f.message}
|
|
58
|
+
`),process.exit(1)}}s||(console.log(""),s=await ge(n)),l||(console.log(""),l=await de(s,n));let a=N(o);if(console.log(`
|
|
18
59
|
Triggering Workflow
|
|
19
|
-
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${
|
|
20
|
-
Your workflow execution quota has been exceeded`),
|
|
21
|
-
`),process.exit(1)}let
|
|
22
|
-
`),process.exit(1)}}export{
|
|
60
|
+
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${l}`),console.log(` Project: ${s}`),Object.keys(a).length>0){let c=JSON.stringify(a);console.log(` Input: ${c.length>60?`${c.substring(0,57)}...`:c}`)}o.idempotencyKey&&console.log(` Idempotency: ${o.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");let r=T("Triggering workflow execution...").start();try{let c=k(),f={input:a};o.idempotencyKey&&(f.idempotencyKey=o.idempotencyKey);let g=await fetch(`${c}/projects/${s}/workflows/${l}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(f)});if(!g.ok){let d=await g.json().catch(()=>({}));g.status===429&&(r.fail("Quota exceeded"),console.log(`
|
|
61
|
+
Your workflow execution quota has been exceeded`),d.quotaInfo&&(console.log(` Used: ${d.quotaInfo.used}/${d.quotaInfo.limit} executions`),console.log(` Plan: ${d.quotaInfo.planId}`),d.quotaInfo.periodEnd&&console.log(` Resets: ${new Date(d.quotaInfo.periodEnd).toLocaleDateString()}`)),console.log(""),process.exit(1)),r.fail("Trigger failed"),console.log(` Error: ${d.message||g.statusText}
|
|
62
|
+
`),process.exit(1)}let u=await g.json();if(r.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${u.jobId}`),console.log(` Status: ${u.status}`),console.log(` Version: ${u.version}`),console.log(` Triggered: ${new Date(u.triggeredAt).toLocaleString()}`),console.log(""),o.follow){console.log(" Streaming logs (Ctrl+C to stop)..."),console.log("");let{logsCommand:d}=await Promise.resolve().then(()=>(z(),O));return d(u.jobId,{follow:!0,project:s,apiKey:o.apiKey})}console.log(" Monitor execution:"),e?(console.log(` zibby workflow logs ${e}`),console.log(` zibby workflow logs ${e} -t`)):(console.log(` zibby workflow logs --workflow ${l} --project ${s}`),console.log(` zibby workflow logs --workflow ${l} --project ${s} -t`)),console.log("")}catch(c){r.fail("Trigger failed"),console.log(` Error: ${c.message}
|
|
63
|
+
`),process.exit(1)}}export{j as coerceValue,_ as parseParams,N as resolveInput,Pe as triggerWorkflowCommand};
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "node ../scripts/build.mjs --extra-dirs bin",
|
|
11
|
-
"test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js test/deploy-bundles-user-config.test.js test/run-loads-user-config.test.js test/env-helpers.test.js test/env-cli.test.js test/chat-agents.test.js test/chat-agents-api.test.js test/chat-agents-picker.test.js test/chat-sandbox-attach.test.js test/credentials-file.test.js test/credentials-api.test.js test/credentials-loader.test.js test/cli-namespace-consistency.test.js test/cli-workflow-subcommands.test.js test/run-bundle-core-import.test.js test/start-respects-config.test.js test/sse-backoff.test.js test/sse-reconnect-loop.test.js test/run-helpers.test.js test/sse-parser.test.js test/cloud-creds-check.test.js",
|
|
11
|
+
"test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js test/deploy-bundles-user-config.test.js test/deploy-skip-unchanged.test.js test/deploy-warm-flag.test.js test/run-loads-user-config.test.js test/env-helpers.test.js test/env-cli.test.js test/chat-agents.test.js test/chat-agents-api.test.js test/chat-agents-picker.test.js test/chat-sandbox-attach.test.js test/credentials-file.test.js test/credentials-api.test.js test/credentials-loader.test.js test/cli-namespace-consistency.test.js test/cli-workflow-subcommands.test.js test/run-bundle-core-import.test.js test/start-respects-config.test.js test/sse-backoff.test.js test/sse-reconnect-loop.test.js test/run-helpers.test.js test/run-banner.test.js test/run-banner-e2e.test.js test/sse-parser.test.js test/cloud-creds-check.test.js",
|
|
12
12
|
"test:unit": "vitest run src/",
|
|
13
13
|
"test:auth": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
|
|
14
14
|
"lint": "eslint .",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
36
|
"@zibby/agent-workflow": "^0.3.2",
|
|
37
|
-
"@zibby/core": "^0.3.
|
|
37
|
+
"@zibby/core": "^0.3.6",
|
|
38
38
|
"@zibby/ui-memory": "^1.0.0",
|
|
39
39
|
"@zibby/skills": "^0.1.11",
|
|
40
40
|
"adm-zip": "^0.5.17",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "node ../scripts/build.mjs --extra-dirs bin",
|
|
11
|
-
"test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js test/deploy-bundles-user-config.test.js test/run-loads-user-config.test.js test/env-helpers.test.js test/env-cli.test.js test/chat-agents.test.js test/chat-agents-api.test.js test/chat-agents-picker.test.js test/chat-sandbox-attach.test.js test/credentials-file.test.js test/credentials-api.test.js test/credentials-loader.test.js test/cli-namespace-consistency.test.js test/cli-workflow-subcommands.test.js test/run-bundle-core-import.test.js test/start-respects-config.test.js test/sse-backoff.test.js test/sse-reconnect-loop.test.js test/run-helpers.test.js test/sse-parser.test.js test/cloud-creds-check.test.js",
|
|
11
|
+
"test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js test/deploy-bundles-user-config.test.js test/deploy-skip-unchanged.test.js test/deploy-warm-flag.test.js test/run-loads-user-config.test.js test/env-helpers.test.js test/env-cli.test.js test/chat-agents.test.js test/chat-agents-api.test.js test/chat-agents-picker.test.js test/chat-sandbox-attach.test.js test/credentials-file.test.js test/credentials-api.test.js test/credentials-loader.test.js test/cli-namespace-consistency.test.js test/cli-workflow-subcommands.test.js test/run-bundle-core-import.test.js test/start-respects-config.test.js test/sse-backoff.test.js test/sse-reconnect-loop.test.js test/run-helpers.test.js test/run-banner.test.js test/run-banner-e2e.test.js test/sse-parser.test.js test/cloud-creds-check.test.js",
|
|
12
12
|
"test:unit": "vitest run src/",
|
|
13
13
|
"test:auth": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
|
|
14
14
|
"lint": "eslint .",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
36
|
"@zibby/agent-workflow": "^0.3.2",
|
|
37
|
-
"@zibby/core": "^0.3.
|
|
37
|
+
"@zibby/core": "^0.3.6",
|
|
38
38
|
"@zibby/ui-memory": "^1.0.0",
|
|
39
39
|
"@zibby/skills": "^0.1.11",
|
|
40
40
|
"adm-zip": "^0.5.17",
|