@zibby/cli 0.4.10 → 0.4.12

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,4 +1,4 @@
1
- import{readdir as wo,stat as ho}from"fs/promises";import{existsSync as P}from"fs";import{join as S}from"path";import r from"chalk";import bo from"dotenv";import{existsSync as Q}from"fs";import{join as oo}from"path";import{pathToFileURL as eo}from"url";async function C(o){let e=oo(o,".zibby.config.mjs");if(!Q(e))throw new Error(".zibby.config.mjs not found");try{let t=await import(eo(e).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}var j={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 I(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";j[e]?o=j[e].apiUrl:o=j.prod.apiUrl}try{let e=new URL(o);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),j.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),j.prod.apiUrl}}import{existsSync as fo,readFileSync as go}from"fs";import{join as yo}from"path";import E from"chalk";import{confirm as mo}from"@inquirer/prompts";import s from"chalk";import z from"ora";import{spawn as lo}from"child_process";import{existsSync as B,mkdirSync as no,readFileSync as to,writeFileSync as ro}from"fs";import{homedir as R}from"os";import{join as A}from"path";function L(){return process.env.ZIBBY_CONFIG_DIR||A(R(),".zibby")}function D(){return A(L(),"config.json")}var so=A(R(),".zibby"),Ao=A(so,"config.json");function io(){let o=L();B(o)||no(o,{recursive:!0})}function k(){try{let o=D();if(B(o)){let e=to(o,"utf-8");return JSON.parse(e)}}catch{}return{}}function U(o){io(),ro(D(),JSON.stringify(o,null,2))}function O(){return k().sessionToken||null}function Y(o){let e=k();e.sessionToken=o,U(e)}function F(){return k().user||null}function Z(o){let e=k();e.user=o,U(e)}function K(o){let e=k();e.proxyUrl=o,U(e)}function M(o){let e=k();e.mem0ProxyUrl=o,U(e)}function J(o){let e=k();e.projects=o,U(e)}import{existsSync as _o,mkdirSync as Eo,readFileSync as No,writeFileSync as Co,unlinkSync as Bo}from"fs";import{resolve as Lo}from"path";import{homedir as Oo}from"os";function co(o){let e=process.platform;try{let t,l;return e==="darwin"?(t="open",l=[o]):e==="win32"?(t="cmd",l=["/c","start","",o]):(t="xdg-open",l=[o]),lo(t,l,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function ao(){let o=O(),e=F();return o&&e?{loggedIn:!0,user:e,token:o}:{loggedIn:!1}}async function V(){try{console.log(s.cyan(`
1
+ import{readdir as wo,stat as ho}from"fs/promises";import{existsSync as P}from"fs";import{join as S}from"path";import r from"chalk";import ko from"dotenv";import{existsSync as Q}from"fs";import{join as oo}from"path";import{pathToFileURL as eo}from"url";async function C(o){let e=oo(o,".zibby.config.mjs");if(!Q(e))throw new Error(".zibby.config.mjs not found");try{let t=await import(eo(e).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}var j={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 I(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";j[e]?o=j[e].apiUrl:o=j.prod.apiUrl}try{let e=new URL(o);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),j.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),j.prod.apiUrl}}import{existsSync as fo,readFileSync as go}from"fs";import{join as yo}from"path";import E from"chalk";import{confirm as mo}from"@inquirer/prompts";import s from"chalk";import _ from"ora";import{spawn as lo}from"child_process";import{existsSync as B,mkdirSync as no,readFileSync as to,writeFileSync as ro}from"fs";import{homedir as R}from"os";import{join as A}from"path";function L(){return process.env.ZIBBY_CONFIG_DIR||A(R(),".zibby")}function D(){return A(L(),"config.json")}var so=A(R(),".zibby"),Ao=A(so,"config.json");function io(){let o=L();B(o)||no(o,{recursive:!0})}function b(){try{let o=D();if(B(o)){let e=to(o,"utf-8");return JSON.parse(e)}}catch{}return{}}function U(o){io(),ro(D(),JSON.stringify(o,null,2))}function O(){return b().sessionToken||null}function Y(o){let e=b();e.sessionToken=o,U(e)}function F(){return b().user||null}function Z(o){let e=b();e.user=o,U(e)}function K(o){let e=b();e.proxyUrl=o,U(e)}function M(o){let e=b();e.mem0ProxyUrl=o,U(e)}function J(o){let e=b();e.projects=o,U(e)}import{existsSync as zo,mkdirSync as Eo,readFileSync as No,writeFileSync as Co,unlinkSync as Bo}from"fs";import{resolve as Lo}from"path";import{homedir as Oo}from"os";function co(o){let e=process.platform;try{let t,l;return e==="darwin"?(t="open",l=[o]):e==="win32"?(t="cmd",l=["/c","start","",o]):(t="xdg-open",l=[o]),lo(t,l,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function ao(){let o=O(),e=F();return o&&e?{loggedIn:!0,user:e,token:o}:{loggedIn:!1}}async function V(){try{console.log(s.cyan(`
2
2
  \u{1F510} Initiating login...
3
3
  `));let o=ao();if(o.loggedIn){console.log(s.green("\u2705 Already logged in!")),console.log(s.gray(`User: ${o.user.email}`)),console.log(s.gray(`Name: ${o.user.name}
4
4
  `));let{createInterface:e}=await import("readline"),t=e({input:process.stdin,output:process.stdout});return new Promise((l,u)=>{let i=()=>{t.close(),process.stdin.isTTY&&process.stdin.setRawMode(!1)},c=()=>{console.log(s.yellow(`
@@ -7,14 +7,14 @@ import{readdir as wo,stat as ho}from"fs/promises";import{existsSync as P}from"fs
7
7
  `)),i(),process.exit(0)};process.on("SIGINT",c),t.question(s.yellow("Continue with this session? (Y/n): "),async a=>{process.removeListener("SIGINT",c),i();try{if(a.toLowerCase()==="n"||a.toLowerCase()==="no"){console.log(s.gray(`Starting new login...
8
8
  `));let m=await W();l(m)}else console.log(s.green(`Using existing session.
9
9
  `)),l({success:!0,...o})}catch(m){u(m)}})})}return await W()}catch(o){return console.error(s.red(`
10
- \u274C Login failed:`,o.message)),{success:!1,error:o.message}}}async function uo(o){let e=I();try{let t=await fetch(`${e}/projects`,{headers:{Authorization:`Bearer ${o}`}});if(t.ok){let u=((await t.json()).projects||[]).map(i=>({name:i.name,projectId:i.projectId,apiToken:i.apiToken}));return J(u),u}}catch(t){console.log(s.gray(`\u26A0\uFE0F Could not fetch projects: ${t.message}`))}return[]}async function W(){let o=I(),e=z("Requesting login code...").start(),t=await fetch(`${o}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!t.ok){e.fail("Failed to request login code");let w=await t.json();throw new Error(w.error||"Failed to initiate login")}let{deviceCode:l,userCode:u,verificationUrl:i,expiresIn:c,interval:a}=await t.json();e.succeed("Login code generated"),console.log(""),console.log(s.cyan("\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\u2550\u2550\u2557")),console.log(s.cyan("\u2551")+s.white.bold(" Complete login in your browser ")+s.cyan("\u2551")),console.log(s.cyan("\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\u2550\u2550\u255D")),console.log(""),console.log(s.white("Opening browser to login page...")),console.log(s.gray(`Code expires in ${Math.floor(c/60)} minutes`)),console.log(""),await co(i)||(console.log(s.yellow("\u26A0\uFE0F Could not open browser automatically.")),console.log(s.white("Please open this URL manually: ")+s.blue(i)),console.log(""));let f=z("Waiting for authorization...").start(),g=(a||3)*1e3,h=Math.floor(c/(a||3)),T=0,x=!1,$=()=>{x=!0,f.stop(),console.log(s.yellow(`
10
+ \u274C Login failed:`,o.message)),{success:!1,error:o.message}}}async function uo(o){let e=I();try{let t=await fetch(`${e}/projects`,{headers:{Authorization:`Bearer ${o}`}});if(t.ok){let u=((await t.json()).projects||[]).map(i=>({name:i.name,projectId:i.projectId,apiToken:i.apiToken}));return J(u),u}}catch(t){console.log(s.gray(`\u26A0\uFE0F Could not fetch projects: ${t.message}`))}return[]}async function W(){let o=I(),e=_("Requesting login code...").start(),t=await fetch(`${o}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!t.ok){e.fail("Failed to request login code");let w=await t.json();throw new Error(w.error||"Failed to initiate login")}let{deviceCode:l,userCode:u,verificationUrl:i,expiresIn:c,interval:a}=await t.json();e.succeed("Login code generated"),console.log(""),console.log(s.cyan("\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\u2550\u2550\u2557")),console.log(s.cyan("\u2551")+s.white.bold(" Complete login in your browser ")+s.cyan("\u2551")),console.log(s.cyan("\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\u2550\u2550\u255D")),console.log(""),console.log(s.white("Opening browser to login page...")),console.log(s.gray(`Code expires in ${Math.floor(c/60)} minutes`)),console.log(""),await co(i)||(console.log(s.yellow("\u26A0\uFE0F Could not open browser automatically.")),console.log(s.white("Please open this URL manually: ")+s.blue(i)),console.log(""));let f=_("Waiting for authorization...").start(),g=(a||3)*1e3,h=Math.floor(c/(a||3)),T=0,x=!1,$=()=>{x=!0,f.stop(),console.log(s.yellow(`
11
11
 
12
12
  \u26A0\uFE0F Login cancelled
13
- `)),process.exit(0)};process.on("SIGINT",$);try{for(;T<h&&!x;){await po(g),T++;let w=await fetch(`${o}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:l})});if(w.status===202)continue;if(!w.ok){f.fail("Authorization failed");let p=await w.json();throw new Error(p.error||"Authorization failed")}let n=await w.json();if(n.status==="authorized"){f.succeed(s.white("Authorization successful!")),Y(n.token),Z(n.user),n.proxyUrl&&K(n.proxyUrl),n.mem0ProxyUrl&&M(n.mem0ProxyUrl),console.log(""),console.log(s.gray(`User: ${n.user.email}`));let p=z("Fetching projects...").start(),y=await uo(n.token);return p.succeed(`Fetched ${y.length} project${y.length!==1?"s":""}`),console.log(s.gray(`Session saved to: ~/.zibby/config.json
14
- `)),{success:!0,loggedIn:!0,user:n.user,token:n.token}}if(n.status==="denied")throw f.fail("Authorization denied"),new Error("User denied authorization")}throw f.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",$)}}function po(o){return new Promise(e=>setTimeout(e,o))}function G(){try{let o=process.env.HOME||process.env.USERPROFILE;if(!o)return null;let e=yo(o,".zibby","config.json");return fo(e)&&JSON.parse(go(e,"utf-8")).sessionToken||null}catch{return null}}function _(){console.log(`
13
+ `)),process.exit(0)};process.on("SIGINT",$);try{for(;T<h&&!x;){await po(g),T++;let w=await fetch(`${o}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:l})});if(w.status===202)continue;if(!w.ok){f.fail("Authorization failed");let p=await w.json();throw new Error(p.error||"Authorization failed")}let n=await w.json();if(n.status==="authorized"){f.succeed(s.white("Authorization successful!")),Y(n.token),Z(n.user),n.proxyUrl&&K(n.proxyUrl),n.mem0ProxyUrl&&M(n.mem0ProxyUrl),console.log(""),console.log(s.gray(`User: ${n.user.email}`));let p=_("Fetching projects...").start(),y=await uo(n.token);return p.succeed(`Fetched ${y.length} project${y.length!==1?"s":""}`),console.log(s.gray(`Session saved to: ~/.zibby/config.json
14
+ `)),{success:!0,loggedIn:!0,user:n.user,token:n.token}}if(n.status==="denied")throw f.fail("Authorization denied"),new Error("User denied authorization")}throw f.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",$)}}function po(o){return new Promise(e=>setTimeout(e,o))}function G(){try{let o=process.env.HOME||process.env.USERPROFILE;if(!o)return null;let e=yo(o,".zibby","config.json");return fo(e)&&JSON.parse(go(e,"utf-8")).sessionToken||null}catch{return null}}function z(){console.log(`
15
15
  Not authenticated.`),console.log(` Run ${E.cyan("zibby login")} or set ${E.cyan("ZIBBY_API_KEY")} in your environment.
16
- `)}async function q(o={}){let e=o.apiKey||process.env.ZIBBY_API_KEY||null,t=G();if(t||e)return{sessionToken:t,apiKey:e};if(!process.stdin.isTTY){if(o.optional)return{sessionToken:null,apiKey:null};_(),process.exit(1)}console.log(E.yellow(`
17
- Not logged in.`));let l;try{l=await mo({message:"Open browser to log in now?",default:!0})}catch{l=!1}if(!l){if(o.optional)return{sessionToken:null,apiKey:null};_(),process.exit(1)}if(await V(),t=G(),!t){if(o.optional)return{sessionToken:null,apiKey:null};_(),process.exit(1)}return{sessionToken:t,apiKey:null}}bo.config();async function ko(o={}){let e=process.cwd(),t=".zibby/workflows";try{t=(await C(e))?.paths?.workflows||".zibby/workflows"}catch{}let l=S(e,t);if(!P(l))return o.quiet?[]:(console.log(r.yellow(`
16
+ `)}async function q(o={}){let e=o.apiKey||process.env.ZIBBY_API_KEY||null,t=G();if(t||e)return{sessionToken:t,apiKey:e};if(!process.stdin.isTTY){if(o.optional)return{sessionToken:null,apiKey:null};z(),process.exit(1)}console.log(E.yellow(`
17
+ Not logged in.`));let l;try{l=await mo({message:"Open browser to log in now?",default:!0})}catch{l=!1}if(!l){if(o.optional)return{sessionToken:null,apiKey:null};z(),process.exit(1)}if(await V(),t=G(),!t){if(o.optional)return{sessionToken:null,apiKey:null};z(),process.exit(1)}return{sessionToken:t,apiKey:null}}ko.config();async function bo(o={}){let e=process.cwd(),t="workflows";try{t=(await C(e))?.paths?.workflows||"workflows"}catch{}let l=S(e,t);if(!P(l))return o.quiet?[]:(console.log(r.yellow(`
18
18
  No workflows found in ${t}/`)),console.log(r.gray(` Create one with: zibby workflow new <name>
19
19
  `)),[]);try{let u=await wo(l),i=[];for(let c of u){let a=S(l,c);if(!(await ho(a)).isDirectory())continue;let f=P(S(a,"graph.mjs"))||P(S(a,"graph.js")),g=P(S(a,"workflow.json"));!f&&!g||i.push({name:c,hasGraph:f,hasManifest:g,path:`${t}/${c}`,source:"local"})}if(o.quiet)return i;if(i.length===0)return console.log(r.yellow(`
20
20
  No workflows found in ${t}/`)),console.log(r.gray(` Create one with: zibby workflow new <name>
@@ -24,12 +24,12 @@ import{readdir as wo,stat as ho}from"fs/promises";import{existsSync as P}from"fs
24
24
  Total: ${i.length} workflow${i.length===1?"":"s"}
25
25
  `)),console.log(r.white(" Commands:")),console.log(r.cyan(" zibby workflow run <name> ")+r.gray("Run locally")),console.log(r.cyan(" zibby workflow deploy <name> ")+r.gray("Deploy to cloud")),console.log(r.cyan(" zibby workflow trigger <uuid> ")+r.gray("Run workflow (returns job ID)")),console.log(r.cyan(" zibby workflow logs <uuid> ")+r.gray("Tail execution logs")),console.log(""),i}catch(u){if(o.quiet)return[];console.log(r.red(`
26
26
  Error reading workflows: ${u.message}
27
- `)),process.exit(1)}}async function pe(o={}){let e=await ko({...o,quiet:!0}),{sessionToken:t,apiKey:l}=await q({apiKey:o.apiKey,optional:!0}),u=[],i=t||l;if(i)try{let n=I(),p=await fetch(`${n}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(p.ok){let b=(await p.json()).projects||[];for(let v of b){let N=await fetch(`${n}/projects/${v.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(N.ok){let H=await N.json(),X=["analysis","implementation","run_test"];for(let d of H)X.includes(d.workflowType)||u.push({uuid:d.uuid,name:d.workflowType,projectId:v.projectId,projectName:v.name||v.projectId,version:d.version||0,nodes:d.graphJson?JSON.parse(d.graphJson).nodes?.length:0,updatedAt:d.updatedAt||null,source:"remote",warmEnabled:d.warmEnabled===!0,warmCount:Number(d.warmCount)||0,usesDedicatedEgress:!!d.usesDedicatedEgress})}}}}catch{}let c=[],a=new Map(e.map(n=>[n.name,n]));for(let n of u)c.push({uuid:n.uuid,name:n.name,project:n.projectName,version:n.version,warm:n.warmEnabled?String(n.warmCount||1):"-",egress:n.usesDedicatedEgress?"static":"-"});for(let[n,p]of a.entries())u.some(b=>b.name===n)||c.push({uuid:null,name:p.name,project:"-",version:"-",warm:"-",egress:"-"});if(c.length===0){console.log(`
27
+ `)),process.exit(1)}}async function pe(o={}){let e=await bo({...o,quiet:!0}),{sessionToken:t,apiKey:l}=await q({apiKey:o.apiKey,optional:!0}),u=[],i=t||l;if(i)try{let n=I(),p=await fetch(`${n}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(p.ok){let k=(await p.json()).projects||[];for(let v of k){let N=await fetch(`${n}/projects/${v.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(N.ok){let H=await N.json(),X=["analysis","implementation","run_test"];for(let d of H)X.includes(d.workflowType)||u.push({uuid:d.uuid,name:d.workflowType,projectId:v.projectId,projectName:v.name||v.projectId,version:d.version||0,nodes:d.graphJson?JSON.parse(d.graphJson).nodes?.length:0,updatedAt:d.updatedAt||null,source:"remote",warmEnabled:d.warmEnabled===!0,warmCount:Number(d.warmCount)||0,usesDedicatedEgress:!!d.usesDedicatedEgress})}}}}catch{}let c=[],a=new Map(e.map(n=>[n.name,n]));for(let n of u)c.push({uuid:n.uuid,name:n.name,project:n.projectName,version:n.version,warm:n.warmEnabled?String(n.warmCount||1):"-",egress:n.usesDedicatedEgress?"static":"-"});for(let[n,p]of a.entries())u.some(k=>k.name===n)||c.push({uuid:null,name:p.name,project:"-",version:"-",warm:"-",egress:"-"});if(c.length===0){console.log(`
28
28
  No workflows found
29
29
  `),console.log(` Create one with: zibby workflow new <name>
30
30
  `);return}let m=c.map(n=>({uuid:n.uuid||"-",name:n.name,project:n.project,version:String(n.version),warm:n.warm||"-",egress:n.egress||"-"})),f={uuid:"UUID",name:"Name",project:"Project",version:"Ver",warm:"Warm",egress:"Egress"},g=["uuid","name","project","version","warm","egress"],h=Object.fromEntries(g.map(n=>[n,Math.max(f[n].length,...m.map(p=>String(p[n]).length))])),T=`\u250C${g.map(n=>"\u2500".repeat(h[n]+2)).join("\u252C")}\u2510`,x=`\u251C${g.map(n=>"\u2500".repeat(h[n]+2)).join("\u253C")}\u2524`,$=`\u2514${g.map(n=>"\u2500".repeat(h[n]+2)).join("\u2534")}\u2518`,w=`\u2502${g.map(n=>` ${f[n].padEnd(h[n])} `).join("\u2502")}\u2502`;console.log(`
31
31
  Workflows
32
- `),console.log(` ${T}`),console.log(` ${r.bold(w)}`),console.log(` ${x}`);for(let n of m){let p=g.map(y=>{let b=String(n[y]).padEnd(h[y]);return` ${y==="uuid"&&n.uuid!=="-"?r.cyan(b):y==="name"?r.white(b):b} `});console.log(` \u2502${p.join("\u2502")}\u2502`)}console.log(` ${$}`),console.log(`
32
+ `),console.log(` ${T}`),console.log(` ${r.bold(w)}`),console.log(` ${x}`);for(let n of m){let p=g.map(y=>{let k=String(n[y]).padEnd(h[y]);return` ${y==="uuid"&&n.uuid!=="-"?r.cyan(k):y==="name"?r.white(k):k} `});console.log(` \u2502${p.join("\u2502")}\u2502`)}console.log(` ${$}`),console.log(`
33
33
  Total: ${c.length} workflow${c.length===1?"":"s"}
34
34
  `),console.log(" Commands:"),console.log(" zibby workflow new <name> Scaffold a new workflow"),console.log(" zibby workflow run <name> Run locally"),console.log(" zibby workflow deploy <name> Ship to cloud (generates UUID on first deploy)"),console.log(" zibby workflow trigger <uuid> Run a deployed workflow remotely"),console.log(" zibby workflow logs <uuid> Tail logs from a remote run"),console.log(" zibby workflow download <uuid> Pull remote back to local (then edit + redeploy)"),console.log(" zibby workflow delete <uuid> Delete a deployed workflow"),i||console.log(`
35
- Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{pe as listAllWorkflowsCommand,ko as listLocalWorkflowsCommand};
35
+ Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{pe as listAllWorkflowsCommand,bo as listLocalWorkflowsCommand};
@@ -1,42 +1,42 @@
1
- import e from"chalk";import{readFileSync as v,existsSync as N,writeSync as R}from"fs";import{homedir as C}from"os";import{join as _}from"path";var x="https://logs.workflows.zibby.app",j="https://logs-stream.zibby.app/",b=null;async function A(i){return b||(process.env.ZIBBY_SSE_ENDPOINT?(b=process.env.ZIBBY_SSE_ENDPOINT,b):(b=j,b))}function L(i){let r=_(C(),".zibby","config.json");N(r)||(console.log(e.red(`
1
+ import e from"chalk";import{readFileSync as M,existsSync as O,writeSync as F}from"fs";import{homedir as z}from"os";import{join as B}from"path";var A="https://logs.workflows.zibby.app",J="https://logs-stream.zibby.app/",P=null;async function U(a){return P||(process.env.ZIBBY_SSE_ENDPOINT?(P=process.env.ZIBBY_SSE_ENDPOINT,P):(P=J,P))}function G(a){let s=B(z(),".zibby","config.json");O(s)||(console.log(e.red(`
2
2
  Not authenticated`)),console.log(e.gray(` Run: zibby login
3
- `)),process.exit(1));let s;try{s=JSON.parse(v(r,"utf-8"))}catch{console.log(e.red(`
3
+ `)),process.exit(1));let n;try{n=JSON.parse(M(s,"utf-8"))}catch{console.log(e.red(`
4
4
  Config file corrupt`)),console.log(e.gray(` Run: zibby login
5
- `)),process.exit(1)}let o=s.sessionToken;o||(console.log(e.red(`
5
+ `)),process.exit(1)}let o=n.sessionToken;o||(console.log(e.red(`
6
6
  Not authenticated`)),console.log(e.gray(` Run: zibby login
7
- `)),process.exit(1));let f=i.project;return{token:o,projectId:f}}function k(i){return new Date(i).toISOString().replace("T"," ").replace("Z","")}async function E(i,r){let s=await fetch(i,{headers:{Authorization:`Bearer ${r}`}});if(!s.ok){let o=await s.text();throw new Error(`API ${s.status}: ${o}`)}return s.json()}async function O(i,r,s,o){return i||(console.log(e.red(`
7
+ `)),process.exit(1));let f=a.project;return{token:o,projectId:f}}function C(a){return new Date(a).toISOString().replace("T"," ").replace("Z","")}async function j(a,s){let n=await fetch(a,{headers:{Authorization:`Bearer ${s}`}});if(!n.ok){let o=await n.text();throw new Error(`API ${n.status}: ${o}`)}return n.json()}async function W(a,s,n,o){return a||(console.log(e.red(`
8
8
  Workflow UUID is required`)),console.log(e.gray(" Usage: zibby workflow logs <workflow-uuid>")),console.log(e.gray(` zibby workflow logs <workflow-uuid> -t
9
- `)),process.exit(1)),i}function F(i,r){let o=((i||"")+r).split(`
10
- `),f=o.pop()||"",a=[],u=null,n=null;for(let d=0;d<o.length;d++){let l=o[d];if(l.trim()){if(l.startsWith("id:")){u=l.slice(3).trim();continue}if(l.startsWith("event:")){let g=l.slice(6).trim();if(g==="log")continue;if(g==="status"){let c=o[d+1];if(c&&c.startsWith("data:"))try{let y=JSON.parse(c.slice(5).trim());y.status==="new_execution"?a.push({type:"newExecution",executionId:y.executionId,taskId:y.taskId}):y.status==="waiting"&&a.push({type:"waiting"})}catch{}continue}if(g==="complete"){a.push({type:"complete"});continue}if(g==="error"){let c=o[d+1];if(c&&c.startsWith("data:"))try{if(JSON.parse(c.slice(5).trim()).error==="No executions found for workflow"){n={type:"notFound"};break}}catch{}n={type:"failed"};break}continue}if(l.startsWith("data:")){let g=l.slice(5).trim();if(!g)continue;try{let c=JSON.parse(g);c.timestamp&&c.message&&a.push({type:"log",timestamp:c.timestamp,message:c.message,taskId:c.taskId})}catch{}}}}return{actions:a,remainder:f,lastEventId:u,returnSignal:n}}async function J({token:i,executionId:r,sseEndpoint:s,stopped:o}){let f=null;try{let a=new URL(s);a.searchParams.set("jobId",r),f&&a.searchParams.set("lastEventId",f);let u=await fetch(a.toString(),{headers:{Authorization:`Bearer ${i}`,Accept:"text/event-stream"}});if(!u.ok)throw new Error(`SSE connection failed: ${u.status} ${u.statusText}`);let n=u.body.getReader(),d=new TextDecoder,l="",g=!1;for(;!o.value;){let{done:c,value:y}=await n.read();if(c)break;let w=F(l,d.decode(y,{stream:!0}));l=w.remainder,w.lastEventId&&(f=w.lastEventId);for(let t of w.actions)switch(t.type){case"newExecution":{let m=`${t.executionId.slice(0,8)}...${t.executionId.slice(-4)}`,h=t.taskId?t.taskId.slice(-8):"pending";console.log(e.cyan(`
11
- \u250C\u2500 Execution: ${m} (task: ${h})`)),console.log(e.cyan(` \u2514\u2500 Streaming logs...
12
- `));break}case"waiting":console.log(e.gray(`
13
- Waiting for next execution...`));break;case"complete":g=!0;break;case"log":{let m=e.gray(k(t.timestamp)),h=t.taskId?e.gray(`(${t.taskId.slice(-8)}) `):"";console.log(`${m} ${h}${t.message.replace(/\n$/,"")}`);break}}if(w.returnSignal)return w.returnSignal.type==="notFound"?{notFound:!0}:{failed:!0}}return{completed:g}}catch(a){if(a.name==="AbortError")return{aborted:!0};throw a}}function M(i,{baseMs:r=500,capMs:s=3e4,rand:o=Math.random}={}){let f=Math.min(s,r*Math.pow(2,Math.max(0,i)));return Math.floor(o()*f)}async function z({attemptStream:i,stopped:r,follow:s,logger:o,sleep:f=d=>new Promise(l=>setTimeout(l,d)),exit:a=d=>{throw new Error(`exit:${d}`)},backoff:u=M,notFoundPollMs:n=5e3}){let d=0,l=!1;for(;!r.value;){let g;try{g=await i(),d=0}catch(c){if(c.name==="AbortError"||r.value)return{reason:"aborted"};if(l||(o.error(` SSE Error: ${c.message}`),s&&o.gray(" Reconnecting..."),l=!0),!s)return a("error")??{reason:"error"};let y=u(d);d++,await f(y);continue}if(g.aborted||r.value)return{reason:"aborted"};if(g.notFound){if(s){l||(o.yellow(" No executions found yet. Waiting for workflow to be triggered..."),o.gray(" Press Ctrl+C to stop."),l=!0),await f(n);continue}return o.yellow(`
9
+ `)),process.exit(1)),a}function D(a,s){let o=((a||"")+s).split(`
10
+ `),f=o.pop()||"",i=[],u=null,t=null;for(let m=0;m<o.length;m++){let l=o[m];if(l.trim()){if(l.startsWith("id:")){u=l.slice(3).trim();continue}if(l.startsWith("event:")){let d=l.slice(6).trim();if(d==="log")continue;if(d==="status"){let c=o[m+1];if(c&&c.startsWith("data:"))try{let h=JSON.parse(c.slice(5).trim());h.status==="new_execution"?i.push({type:"newExecution",executionId:h.executionId,taskId:h.taskId}):h.status==="waiting"&&i.push({type:"waiting"})}catch{}continue}if(d==="complete"){i.push({type:"complete"});continue}if(d==="error"){let c=o[m+1];if(c&&c.startsWith("data:"))try{if(JSON.parse(c.slice(5).trim()).error==="No executions found for workflow"){t={type:"notFound"};break}}catch{}t={type:"failed"};break}continue}if(l.startsWith("data:")){let d=l.slice(5).trim();if(!d)continue;try{let c=JSON.parse(d);c.timestamp&&c.message&&i.push({type:"log",timestamp:c.timestamp,message:c.message,taskId:c.taskId})}catch{}}}}return{actions:i,remainder:f,lastEventId:u,returnSignal:t}}async function Y({token:a,executionId:s,sseEndpoint:n,stopped:o}){let f=null;try{let y=function(){let b=Array.from(I.entries()).slice(0,c);I.clear();for(let[w,p]of b)I.set(w,p);r=new Set(Array.from(I.values()).map(w=>w.taskId).filter(Boolean));for(let w of[...g.keys()])I.has(w)||g.delete(w)},$=function(k){for(let[b,w]of I)if(w.taskId===k)return b;return null},T=function(k){let b=I.get(k);!b||b.headerPrinted||(console.log(e.cyan(`
11
+ \u250C\u2500 Execution: ${b.shortId} (task: ${b.taskSuffix})`)),console.log(e.cyan(` \u2514\u2500 Streaming logs...
12
+ `)),b.headerPrinted=!0)},v=function(k){let b=e.gray(C(k.timestamp)),w=k.taskId?e.gray(`(${k.taskId.slice(-8)}) `):"";console.log(`${b} ${w}${k.message.replace(/\n$/,"")}`)},R=function(){if(!x)return;x=!1,S&&(clearTimeout(S),S=null);let k=Array.from(I.entries()).reverse();for(let[b]of k){let w=g.get(b);if(!(!w||w.length===0)){T(b);for(let p of w)v(p)}}g.clear()},N=function(){x&&(S&&clearTimeout(S),S=setTimeout(R,h))},i=new URL(n);i.searchParams.set("jobId",s),f&&i.searchParams.set("lastEventId",f);let u=await fetch(i.toString(),{headers:{Authorization:`Bearer ${a}`,Accept:"text/event-stream"}});if(!u.ok)throw new Error(`SSE connection failed: ${u.status} ${u.statusText}`);let t=u.body.getReader(),m=new TextDecoder,l="",d=!1,c=Number(process.env.ZIBBY_LOGS_HISTORY_LIMIT)||10,h=Number(process.env.ZIBBY_LOGS_REPLAY_TIMEOUT_MS)||3e3,I=new Map,r=new Set,g=new Map,x=!0,S=null;for(N();!o.value;){let{done:k,value:b}=await t.read();if(k)break;let w=D(l,m.decode(b,{stream:!0}));l=w.remainder,w.lastEventId&&(f=w.lastEventId);for(let p of w.actions)switch(p.type){case"newExecution":{let E=`${p.executionId.slice(0,8)}...${p.executionId.slice(-4)}`,_=p.taskId?p.taskId.slice(-8):"pending";I.set(p.executionId,{shortId:E,taskSuffix:_,taskId:p.taskId||null,headerPrinted:!1}),g.has(p.executionId)||g.set(p.executionId,[]),y(),N();break}case"waiting":R(),console.log(e.gray(`
13
+ Waiting for next execution...`));break;case"complete":R(),d=!0;break;case"log":{if(p.taskId&&r.size>0&&!r.has(p.taskId))break;if(x){let E=p.taskId?$(p.taskId):null;if(E){let _=g.get(E)||[];_.push(p),g.set(E,_),N()}else v(p)}else{if(p.taskId){let E=$(p.taskId);E&&T(E)}v(p)}break}}if(w.returnSignal)return w.returnSignal.type==="notFound"?{notFound:!0}:{failed:!0}}return R(),{completed:d}}catch(i){if(i.name==="AbortError")return{aborted:!0};throw i}}function H(a,{baseMs:s=500,capMs:n=3e4,rand:o=Math.random}={}){let f=Math.min(n,s*Math.pow(2,Math.max(0,a)));return Math.floor(o()*f)}async function Z({attemptStream:a,stopped:s,follow:n,logger:o,sleep:f=m=>new Promise(l=>setTimeout(l,m)),exit:i=m=>{throw new Error(`exit:${m}`)},backoff:u=H,notFoundPollMs:t=5e3}){let m=0,l=!1;for(;!s.value;){let d;try{d=await a(),m=0}catch(c){if(c.name==="AbortError"||s.value)return{reason:"aborted"};if(l||(o.error(` SSE Error: ${c.message}`),n&&o.gray(" Reconnecting..."),l=!0),!n)return i("error")??{reason:"error"};let h=u(m);m++,await f(h);continue}if(d.aborted||s.value)return{reason:"aborted"};if(d.notFound){if(n){l||(o.yellow(" No executions found yet. Waiting for workflow to be triggered..."),o.gray(" Press Ctrl+C to stop."),l=!0),await f(t);continue}return o.yellow(`
14
14
  No executions found for this workflow. Trigger the workflow first.
15
- `),a("notFound")??{reason:"notFound"}}if(l&&(o.gray(` Reconnected.
16
- `),l=!1),g.failed)return o.red(`
17
- Execution failed.`),s?{reason:"failed"}:a("failed")??{reason:"failed"};if(g.completed)return a("completed")??{reason:"completed"};if(!s)return{reason:"disconnected"}}return{reason:"stopped"}}async function W({token:i,jobId:r,follow:s,projectId:o}){console.log(e.gray(` Streaming logs for workflow ${e.cyan(r)}...`)),console.log(s?e.gray(` Press Ctrl+C to stop.
18
- `):"");let f=await A(i);if(!f)return console.log(e.yellow(` SSE endpoint not configured, using CloudWatch polling...
19
- `)),T({token:i,projectId:null,jobId:r,follow:s,limit:1e5});let a={value:!1},u=()=>{a.value=!0;try{R(2,`
15
+ `),i("notFound")??{reason:"notFound"}}if(l&&(o.gray(` Reconnected.
16
+ `),l=!1),d.failed)return o.red(`
17
+ Execution failed.`),n?{reason:"failed"}:i("failed")??{reason:"failed"};if(d.completed)return i("completed")??{reason:"completed"};if(!n)return{reason:"disconnected"}}return{reason:"stopped"}}async function V({token:a,jobId:s,follow:n,projectId:o}){console.log(e.gray(` Streaming logs for workflow ${e.cyan(s)}...`)),console.log(n?e.gray(` Press Ctrl+C to stop.
18
+ `):"");let f=await U(a);if(!f)return console.log(e.yellow(` SSE endpoint not configured, using CloudWatch polling...
19
+ `)),L({token:a,projectId:null,jobId:s,follow:n,limit:1e5});let i={value:!1},u=()=>{i.value=!0;try{F(2,`
20
20
  Stopped streaming.
21
- `)}catch{}process.exit(0)};process.prependListener("SIGINT",u),process.prependListener("SIGTERM",u),await z({attemptStream:()=>J({token:i,executionId:r,sseEndpoint:f,stopped:a}),stopped:a,follow:s,logger:{gray:n=>console.log(e.gray(n)),red:n=>console.log(e.red(n)),yellow:n=>console.log(e.yellow(n)),error:n=>console.error(e.red(n))},exit:n=>{n==="completed"&&process.exit(0),(n==="error"||n==="notFound"||n==="failed")&&process.exit(1)}})}async function T({token:i,projectId:r,jobId:s,follow:o,limit:f}){let a=r?`${x}/logs/${r}/${s}`:`${x}/job/${s}`,u=null,n=0,d=new Set,l=!1,g=0,c=5,y=()=>{l=!0,console.log(e.gray(`
21
+ `)}catch{}process.exit(0)};process.prependListener("SIGINT",u),process.prependListener("SIGTERM",u),await Z({attemptStream:()=>Y({token:a,executionId:s,sseEndpoint:f,stopped:i}),stopped:i,follow:n,logger:{gray:t=>console.log(e.gray(t)),red:t=>console.log(e.red(t)),yellow:t=>console.log(e.yellow(t)),error:t=>console.error(e.red(t))},exit:t=>{t==="completed"&&process.exit(0),(t==="error"||t==="notFound"||t==="failed")&&process.exit(1)}})}async function L({token:a,projectId:s,jobId:n,follow:o,limit:f}){let i=s?`${A}/logs/${s}/${n}`:`${A}/job/${n}`,u=null,t=0,m=new Set,l=!1,d=0,c=5,h=()=>{l=!0,console.log(e.gray(`
22
22
  Stopped tailing.
23
- `)),process.exit(0)};for(process.on("SIGINT",y),process.on("SIGTERM",y),console.log(e.gray(` Fetching logs for workflow ${e.cyan(s)}...`)),console.log(o?e.gray(` Press Ctrl+C to stop.
24
- `):"");!l;)try{let w=new URLSearchParams({limit:String(f)});u&&w.set("nextToken",u);let t=await E(`${a}?${w}`,i);g=0,t.message&&t.lines?.length===0&&n===0&&console.log(e.gray(` ${t.message}`)),t.status==="starting"&&t.lines?.length===0&&n===0&&console.log(e.gray(" Container starting..."));for(let p of t.lines||[]){let $=`${p.timestamp}:${p.message}`;if(d.has($))continue;d.add($);let I=e.gray(k(p.timestamp)),P=t.taskId?e.gray(`(${t.taskId.slice(-8)}) `):"";console.log(`${I} ${P}${p.message.replace(/\n$/,"")}`)}if(n=t.lines?.length>0?0:n+1,u=t.nextForwardToken||null,t.status==="completed"||t.status==="failed"){let p=t.status==="completed"?e.green:e.red;console.log(p(`
25
- Job ${t.status}.`)),process.exit(t.status==="completed"?0:1)}if(!o){t.status&&console.log(e.gray(`
26
- Status: ${t.status}`));break}let S=t.lines?.length>0?500:n>5?5e3:2e3;await new Promise(p=>setTimeout(p,S))}catch(w){if(w.name==="AbortError")break;w.message.match(/API (400|401|403|404):/)&&(console.error(e.red(`
27
- ${w.message}
28
- `)),process.exit(1)),g++,console.error(e.red(` Error: ${w.message}`)),g>=c&&(console.error(e.red(`
23
+ `)),process.exit(0)};for(process.on("SIGINT",h),process.on("SIGTERM",h),console.log(e.gray(` Fetching logs for workflow ${e.cyan(n)}...`)),console.log(o?e.gray(` Press Ctrl+C to stop.
24
+ `):"");!l;)try{let I=new URLSearchParams({limit:String(f)});u&&I.set("nextToken",u);let r=await j(`${i}?${I}`,a);d=0,r.message&&r.lines?.length===0&&t===0&&console.log(e.gray(` ${r.message}`)),r.status==="starting"&&r.lines?.length===0&&t===0&&console.log(e.gray(" Container starting..."));for(let y of r.lines||[]){let $=`${y.timestamp}:${y.message}`;if(m.has($))continue;m.add($);let T=e.gray(C(y.timestamp)),v=r.taskId?e.gray(`(${r.taskId.slice(-8)}) `):"";console.log(`${T} ${v}${y.message.replace(/\n$/,"")}`)}if(t=r.lines?.length>0?0:t+1,u=r.nextForwardToken||null,r.status==="completed"||r.status==="failed"){let y=r.status==="completed"?e.green:e.red;console.log(y(`
25
+ Job ${r.status}.`)),process.exit(r.status==="completed"?0:1)}if(!o){r.status&&console.log(e.gray(`
26
+ Status: ${r.status}`));break}let S=r.lines?.length>0?500:t>5?5e3:2e3;await new Promise(y=>setTimeout(y,S))}catch(I){if(I.name==="AbortError")break;I.message.match(/API (400|401|403|404):/)&&(console.error(e.red(`
27
+ ${I.message}
28
+ `)),process.exit(1)),d++,console.error(e.red(` Error: ${I.message}`)),d>=c&&(console.error(e.red(`
29
29
  Too many consecutive errors (${c}). Stopping.
30
- `)),process.exit(1)),o||process.exit(1),await new Promise(m=>setTimeout(m,3e3))}}async function U({token:i,projectId:r,workflow:s,follow:o,limit:f}){let a=`${x}/all/${r}`,u=null,n=0,d=new Set,l=null,g=!1,c=0,y=5,w=()=>{g=!0,console.log(e.gray(`
30
+ `)),process.exit(1)),o||process.exit(1),await new Promise(g=>setTimeout(g,3e3))}}async function X({token:a,projectId:s,workflow:n,follow:o,limit:f}){let i=`${A}/all/${s}`,u=null,t=0,m=new Set,l=null,d=!1,c=0,h=5,I=()=>{d=!0,console.log(e.gray(`
31
31
  Stopped tailing.
32
- `)),process.exit(0)};for(process.on("SIGINT",w),process.on("SIGTERM",w),console.log(e.gray(`
33
- Tailing all runs for ${e.cyan(s)}...`)),console.log(o?e.gray(` Press Ctrl+C to stop.
34
- `):"");!g;)try{let t=new URLSearchParams({workflow:s,limit:String(f)});u&&t.set("nextToken",u);let m=await E(`${a}?${t}`,i);c=0,m.message&&m.lines?.length===0&&n===0&&console.log(e.gray(` ${m.message}`));for(let p of m.lines||[]){let $=`${p.timestamp}:${p.jobId}:${p.message}`;if(d.has($))continue;d.add($),p.jobId!==l&&(l!==null&&console.log(""),console.log(e.dim(` \u2500\u2500 ${p.jobId} \u2500\u2500`)),l=p.jobId);let I=e.gray(k(p.timestamp));console.log(`${I} ${p.message.replace(/\n$/,"")}`)}if(n=m.lines?.length>0?0:n+1,u=m.nextToken||null,!o){u&&console.log(e.gray(`
35
- ... more logs available. Run again or use --follow to stream.`)),m.jobCount&&console.log(e.gray(` ${m.jobCount} job(s) found.`));break}if(!m.hasRunning&&!u&&n>2){console.log(e.gray(`
36
- No running jobs. All caught up.`));break}let S=m.lines?.length>0?500:n>5?5e3:2e3;await new Promise(p=>setTimeout(p,S))}catch(t){if(t.name==="AbortError")break;t.message.match(/API (400|401|403|404):/)&&(console.error(e.red(`
37
- ${t.message}
38
- `)),process.exit(1)),c++,console.error(e.red(` Error: ${t.message}`)),c>=y&&(console.error(e.red(`
39
- Too many consecutive errors (${y}). Stopping.
40
- `)),process.exit(1)),o||process.exit(1),await new Promise(h=>setTimeout(h,3e3))}}async function V(i,r){let{token:s,projectId:o}=L(r),f=r.follow===!0,a=r.lines?parseInt(r.lines,10):1e5;if(r.all){let n=r.workflow;return n||(console.log(e.red(`
32
+ `)),process.exit(0)};for(process.on("SIGINT",I),process.on("SIGTERM",I),console.log(e.gray(`
33
+ Tailing all runs for ${e.cyan(n)}...`)),console.log(o?e.gray(` Press Ctrl+C to stop.
34
+ `):"");!d;)try{let r=new URLSearchParams({workflow:n,limit:String(f)});u&&r.set("nextToken",u);let g=await j(`${i}?${r}`,a);c=0,g.message&&g.lines?.length===0&&t===0&&console.log(e.gray(` ${g.message}`));for(let y of g.lines||[]){let $=`${y.timestamp}:${y.jobId}:${y.message}`;if(m.has($))continue;m.add($),y.jobId!==l&&(l!==null&&console.log(""),console.log(e.dim(` \u2500\u2500 ${y.jobId} \u2500\u2500`)),l=y.jobId);let T=e.gray(C(y.timestamp));console.log(`${T} ${y.message.replace(/\n$/,"")}`)}if(t=g.lines?.length>0?0:t+1,u=g.nextToken||null,!o){u&&console.log(e.gray(`
35
+ ... more logs available. Run again or use --follow to stream.`)),g.jobCount&&console.log(e.gray(` ${g.jobCount} job(s) found.`));break}if(!g.hasRunning&&!u&&t>2){console.log(e.gray(`
36
+ No running jobs. All caught up.`));break}let S=g.lines?.length>0?500:t>5?5e3:2e3;await new Promise(y=>setTimeout(y,S))}catch(r){if(r.name==="AbortError")break;r.message.match(/API (400|401|403|404):/)&&(console.error(e.red(`
37
+ ${r.message}
38
+ `)),process.exit(1)),c++,console.error(e.red(` Error: ${r.message}`)),c>=h&&(console.error(e.red(`
39
+ Too many consecutive errors (${h}). Stopping.
40
+ `)),process.exit(1)),o||process.exit(1),await new Promise(x=>setTimeout(x,3e3))}}async function oe(a,s){let{token:n,projectId:o}=G(s),f=s.follow===!0,i=s.lines?parseInt(s.lines,10):1e5;if(s.all){let t=s.workflow;return t||(console.log(e.red(`
41
41
  --workflow is required with --all`)),console.log(e.gray(` Example: zibby workflow logs --workflow ticket-triage --all --project <id>
42
- `)),process.exit(1)),U({token:s,projectId:o,workflow:n,follow:f,limit:a})}let u=await O(i,r,s,o);return f?W({token:s,jobId:u,follow:f,projectId:o}):T({token:s,projectId:o,jobId:u,follow:!1,limit:a})}export{V as logsCommand,F as parseSseChunk,z as runReconnectLoop,M as sseBackoffMs};
42
+ `)),process.exit(1)),X({token:n,projectId:o,workflow:t,follow:f,limit:i})}let u=await W(a,s,n,o);return f?V({token:n,jobId:u,follow:f,projectId:o}):L({token:n,projectId:o,jobId:u,follow:!1,limit:i})}export{oe as logsCommand,D as parseSseChunk,Z as runReconnectLoop,H as sseBackoffMs};
@@ -1,19 +1,19 @@
1
- var L=Object.defineProperty;var U=(e,t)=>()=>(e&&(t=e(e=0)),t);var S=(e,t)=>{for(var o in t)L(e,o,{get:t[o],enumerable:!0})};var P={};S(P,{_resetLoaderCacheForTests:()=>q,loadCredentialsIntoEnv:()=>V});import N from"node:fs";import Y from"node:path";import J from"node:os";async function v(){if(!(process.env.__ZIBBY_CLAUDE_PLAN||process.platform!=="darwin"||!(process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_AUTH_TOKEN)))try{let{execSync:t}=await import("node:child_process"),o=t('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(o){let c=JSON.parse(o)?.claudeAiOauth?.subscriptionType;c&&(process.env.__ZIBBY_CLAUDE_PLAN=c)}}catch{}}function Z(e){try{if(!N.existsSync(e))return{};let t=N.readFileSync(e,"utf-8"),o=JSON.parse(t);return o&&o.agentKeys&&typeof o.agentKeys=="object"?o.agentKeys:{}}catch{return{}}}async function V(e={}){let{verbose:t=!1,force:o=!1,configPath:a}=e;if(w&&!o)return g;if(!!(process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_API_KEY_POOL||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.ANTHROPIC_API_KEY||process.env.ANTHROPIC_AUTH_TOKEN))return await v(),w=!0,g={oauthCount:0,apiCount:0,source:"cloud-env"},t&&console.log("[credentials-loader] env vars already set \u2014 skipping local discovery"),g;let l=a||Y.join(J.homedir(),".zibby","config.json"),n=Z(l),s="none",r=0,f=0;for(let i of G)n[i]&&!process.env[i]&&(process.env[i]=String(n[i]).trim(),s="config.json",i.endsWith("_POOL")?r+=String(n[i]).split(",").filter(u=>u.trim()).length:r+=1);for(let i of M)n[i]&&!process.env[i]&&(process.env[i]=String(n[i]).trim(),s="config.json",i.endsWith("_POOL")?f+=String(n[i]).split(",").filter(u=>u.trim()).length:f+=1);return await v(),w=!0,g={oauthCount:r,apiCount:f,source:s},t&&r+f>0&&console.log(`[credentials-loader] loaded ${r} OAuth + ${f} API from ${s} (~/.zibby/config.json)`),g}function q(){w=!1,g=null}var w,g,G,M,$=U(()=>{w=!1,g=null,G=["CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_OAUTH_TOKEN_POOL","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_AUTH_TOKEN_POOL"],M=["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_POOL"]});import{existsSync as O}from"fs";import{readFile as Q}from"fs/promises";import{join as _}from"path";import{pathToFileURL as X}from"url";import p from"chalk";import oo from"ora";import{existsSync as j}from"fs";import{join as D}from"path";import{pathToFileURL as K}from"url";async function E(e){let t=D(e,".zibby.config.mjs");if(!j(t))throw new Error(".zibby.config.mjs not found");try{let o=await import(K(t).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}import{existsSync as H,readFileSync as B}from"fs";import{resolve as R}from"path";function F(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}function W(e){let t={};for(let o of e||[]){let a=o.indexOf("=");if(a===-1){console.warn(` Warning: ignored param "${o}" \u2014 expected key=value format`);continue}let c=o.slice(0,a).trim(),l=F(o.slice(a+1)),n=c.split("."),s=t;for(let r=0;r<n.length-1;r++)(typeof s[n[r]]!="object"||s[n[r]]===null)&&(s[n[r]]={}),s=s[n[r]];s[n[n.length-1]]=l}return t}function z(e){let t=R(e);H(t)||(console.log(`
1
+ var L=Object.defineProperty;var U=(e,t)=>()=>(e&&(t=e(e=0)),t);var S=(e,t)=>{for(var o in t)L(e,o,{get:t[o],enumerable:!0})};var $={};S($,{_resetLoaderCacheForTests:()=>q,loadCredentialsIntoEnv:()=>V});import v from"node:fs";import z from"node:path";import J from"node:os";async function P(){if(!(process.env.__ZIBBY_CLAUDE_PLAN||process.platform!=="darwin"||!(process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_AUTH_TOKEN)))try{let{execSync:t}=await import("node:child_process"),o=t('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(o){let c=JSON.parse(o)?.claudeAiOauth?.subscriptionType;c&&(process.env.__ZIBBY_CLAUDE_PLAN=c)}}catch{}}function Z(e){try{if(!v.existsSync(e))return{};let t=v.readFileSync(e,"utf-8"),o=JSON.parse(t);return o&&o.agentKeys&&typeof o.agentKeys=="object"?o.agentKeys:{}}catch{return{}}}async function V(e={}){let{verbose:t=!1,force:o=!1,configPath:a}=e;if(w&&!o)return g;if(!!(process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_API_KEY_POOL||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.ANTHROPIC_API_KEY||process.env.ANTHROPIC_AUTH_TOKEN))return await P(),w=!0,g={oauthCount:0,apiCount:0,source:"cloud-env"},t&&console.log("[credentials-loader] env vars already set \u2014 skipping local discovery"),g;let l=a||z.join(J.homedir(),".zibby","config.json"),n=Z(l),r="none",s=0,f=0;for(let i of G)n[i]&&!process.env[i]&&(process.env[i]=String(n[i]).trim(),r="config.json",i.endsWith("_POOL")?s+=String(n[i]).split(",").filter(u=>u.trim()).length:s+=1);for(let i of M)n[i]&&!process.env[i]&&(process.env[i]=String(n[i]).trim(),r="config.json",i.endsWith("_POOL")?f+=String(n[i]).split(",").filter(u=>u.trim()).length:f+=1);return await P(),w=!0,g={oauthCount:s,apiCount:f,source:r},t&&s+f>0&&console.log(`[credentials-loader] loaded ${s} OAuth + ${f} API from ${r} (~/.zibby/config.json)`),g}function q(){w=!1,g=null}var w,g,G,M,b=U(()=>{w=!1,g=null,G=["CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_OAUTH_TOKEN_POOL","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_AUTH_TOKEN_POOL"],M=["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_POOL"]});import{existsSync as y}from"fs";import{readFile as Q}from"fs/promises";import{join as _}from"path";import{pathToFileURL as X}from"url";import p from"chalk";import oo from"ora";import{existsSync as j}from"fs";import{join as D}from"path";import{pathToFileURL as K}from"url";async function E(e){let t=D(e,".zibby.config.mjs");if(!j(t))throw new Error(".zibby.config.mjs not found");try{let o=await import(K(t).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}import{existsSync as H,readFileSync as B}from"fs";import{resolve as R}from"path";function F(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}function W(e){let t={};for(let o of e||[]){let a=o.indexOf("=");if(a===-1){console.warn(` Warning: ignored param "${o}" \u2014 expected key=value format`);continue}let c=o.slice(0,a).trim(),l=F(o.slice(a+1)),n=c.split("."),r=t;for(let s=0;s<n.length-1;s++)(typeof r[n[s]]!="object"||r[n[s]]===null)&&(r[n[s]]={}),r=r[n[s]];r[n[n.length-1]]=l}return t}function Y(e){let t=R(e);H(t)||(console.log(`
2
2
  Error: --input-file not found: ${e}
3
3
  `),process.exit(1));try{return JSON.parse(B(t,"utf-8"))}catch(o){console.log(`
4
4
  Error: --input-file is not valid JSON: ${o.message}
5
- `),process.exit(1)}}function T(e){let t={};if(e.inputFile&&(t={...z(e.inputFile)}),e.input)try{t={...t,...JSON.parse(e.input)}}catch(o){console.log(`
5
+ `),process.exit(1)}}function T(e){let t={};if(e.inputFile&&(t={...Y(e.inputFile)}),e.input)try{t={...t,...JSON.parse(e.input)}}catch(o){console.log(`
6
6
  Error: --input is not valid JSON`),console.log(` ${o.message}
7
- `),process.exit(1)}return e.param?.length&&(t={...t,...W(e.param)}),t}function b({workflowType:e,jobId:t,projectId:o,agentType:a,model:c,egressIp:l,egressKind:n}){let s="\u2500".repeat(60),r=`${a||"default"} (model: ${c||"auto"})`,f=["",s,` Workflow: ${e}`,` Job: ${t||"local"}`,` Project: ${o||"none"}`,` Agent: ${r}`];if(l||n){let i=l||"unknown",u=n||"static";f.push(` Egress: ${i} (${u})`)}return f.push(s),f.join(`
8
- `)}async function eo(e){try{let t=await E(e);return{userConfig:t,workflowsBasePath:t?.paths?.workflows||".zibby/workflows"}}catch{return{userConfig:null,workflowsBasePath:".zibby/workflows"}}}async function to(e,t,o){let a=_(e,"graph.mjs");if(!O(a))throw new Error(`graph.mjs not found in ${o}/${t}/`);let c=await no(e,t),l=await import(X(a).href),n=c.entryClass,s=n&&l[n]||l.default||Object.values(l).find(r=>typeof r=="function"&&r.prototype?.buildGraph);if(!s)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:s,manifest:c}}async function no(e,t){let o=_(e,"workflow.json");if(!O(o))return{name:t,triggers:{api:!0}};let a=await Q(o,"utf-8");return JSON.parse(a)}async function No(e,t={}){e||(console.log(p.red(`
7
+ `),process.exit(1)}return e.param?.length&&(t={...t,...W(e.param)}),t}function N({workflowType:e,jobId:t,projectId:o,agentType:a,model:c,egressIp:l,egressKind:n}){let r="\u2500".repeat(60),s=`${a||"default"} (model: ${c||"auto"})`,f=["",r,` Workflow: ${e}`,` Job: ${t||"local"}`,` Project: ${o||"none"}`,` Agent: ${s}`];if(l||n){let i=l||"unknown",u=n||"static";f.push(` Egress: ${i} (${u})`)}return f.push(r),f.join(`
8
+ `)}async function eo(e){try{let t=await E(e);return{userConfig:t,workflowsBasePath:t?.paths?.workflows||"workflows"}}catch{return{userConfig:null,workflowsBasePath:"workflows"}}}async function to(e,t,o){let a=_(e,"graph.mjs");if(!y(a))throw new Error(`graph.mjs not found in ${o}/${t}/`);let c=await no(e,t),l=await import(X(a).href),n=c.entryClass,r=n&&l[n]||l.default||Object.values(l).find(s=>typeof s=="function"&&s.prototype?.buildGraph);if(!r)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:r,manifest:c}}async function no(e,t){let o=_(e,"workflow.json");if(!y(o))return{name:t,triggers:{api:!0}};let a=await Q(o,"utf-8");return JSON.parse(a)}async function vo(e,t={}){e||(console.log(p.red(`
9
9
  Workflow name is required`)),console.log(p.gray(" Usage: zibby workflow run <workflow-name>")),console.log(p.gray(` Example: zibby workflow run my-pipeline -p ticket=BUG-123
10
- `)),process.exit(1));let o=e.toLowerCase(),a=process.cwd();try{let{loadCredentialsIntoEnv:d}=await Promise.resolve().then(()=>($(),P));await d({verbose:!!process.env.ZIBBY_DEBUG})}catch{}let{userConfig:c,workflowsBasePath:l}=await eo(a),n=_(a,l,o);O(n)||(console.log(p.red(`
10
+ `)),process.exit(1));let o=e.toLowerCase(),a=process.cwd();try{let{loadCredentialsIntoEnv:d}=await Promise.resolve().then(()=>(b(),$));await d({verbose:!!process.env.ZIBBY_DEBUG})}catch{}let{userConfig:c,workflowsBasePath:l}=await eo(a),n=_(a,l,o);y(n)||(console.log(p.red(`
11
11
  Workflow not found: ${l}/${o}/`)),console.log(p.gray(" Create one first:")),console.log(p.cyan(` zibby workflow new ${o}
12
- `)),process.exit(1));let s=T(t),r=oo(` Loading workflow "${o}"...`).start(),f,i;try{({AgentClass:f,manifest:i}=await to(n,o,l)),r.succeed(` Loaded ${p.bold(i.entryClass||f.name)} (${o})`)}catch(d){r.fail(" Failed to load workflow"),console.log(p.red(`
12
+ `)),process.exit(1));let r=T(t),s=oo(` Loading workflow "${o}"...`).start(),f,i;try{({AgentClass:f,manifest:i}=await to(n,o,l)),s.succeed(` Loaded ${p.bold(i.entryClass||f.name)} (${o})`)}catch(d){s.fail(" Failed to load workflow"),console.log(p.red(`
13
13
  ${d.message}
14
- `)),process.exit(1)}let u=`local-${Date.now()}`,k=b({workflowType:o,jobId:u,projectId:c?.projectId,agentType:c?.agent?.provider||process.env.AGENT_TYPE,model:c?.agent?.model||process.env.MODEL});console.log(k);let h=Date.now(),x={input:s,cwd:a,runId:u,config:c||{}},m,y;try{y=new f({workflow:o}),m=await y.buildGraph().run(y,x)}catch(d){let I=((Date.now()-h)/1e3).toFixed(1);console.log(p.red(`
14
+ `)),process.exit(1)}let u=`local-${Date.now()}`,k=N({workflowType:o,jobId:u,projectId:c?.projectId,agentType:c?.agent?.provider||process.env.AGENT_TYPE,model:c?.agent?.model||process.env.MODEL});console.log(k);let h=Date.now(),x={...r,cwd:a,runId:u,config:c||{},input:r},m,O;try{O=new f({workflow:o}),m=await O.buildGraph().run(O,x)}catch(d){let I=((Date.now()-h)/1e3).toFixed(1);console.log(p.red(`
15
15
  \u2716 ${o} failed after ${I}s`)),console.log(p.red(` ${d.message}
16
16
  `)),process.env.ZIBBY_DEBUG&&console.error(d.stack),process.exit(1)}let A=((Date.now()-h)/1e3).toFixed(1),C=m?.success!==!1;C?console.log(p.green(`
17
17
  \u2714 ${o} completed in ${A}s`)):(console.log(p.red(`
18
18
  \u2716 ${o} failed after ${A}s`)),m?.error&&console.log(p.red(` ${m.error}
19
- `))),C||process.exit(1)}export{No as runLocalWorkflowCommand};
19
+ `))),C||process.exit(1)}export{vo as runLocalWorkflowCommand};
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var se=Object.defineProperty;var re=(o,e)=>()=>(o&&(e=o(o=0)),e);var ie=(o,e)=>{for(var t in e)se(o,t,{get:e[t],enumerable:!0})};var Q={};ie(Q,{uploadSessionArtifacts:()=>_e});import{readdirSync as z,statSync as A,createReadStream as ue,existsSync as fe}from"node:fs";import{join as G,relative as ge,sep as me,extname as ye}from"node:path";function Se(o){let e=ye(o).toLowerCase();return he[e]||"application/octet-stream"}function J(o){let e=[],t;try{t=z(o)}catch{return e}for(let s of t){if(we.has(s)||s.startsWith("."))continue;let r=G(o,s),a;try{a=A(r)}catch{continue}a.isDirectory()?e.push(...J(r)):a.isFile()&&e.push(r)}return e}async function Ee({apiUrl:o,apiKey:e,executionId:t,nodeName:s,filename:r,absolutePath:a,sizeBytes:n,contentType:u}){let p;try{let c=await fetch(`${o}/executions/${t}/artifacts/upload-url`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({nodeName:s,filename:r,contentType:u,sizeBytes:n})});if(!c.ok){let i=await c.text();return console.warn(`[artifacts] upload-url failed for ${s}/${r}: ${c.status} ${i.slice(0,200)}`),null}p=await c.json()}catch(c){return console.warn(`[artifacts] upload-url request errored for ${s}/${r}: ${c.message}`),null}try{let c=ue(a),i=await fetch(p.url,{method:"PUT",headers:{"Content-Type":u,"Content-Length":String(n)},body:c,duplex:"half"});if(!i.ok)return console.warn(`[artifacts] S3 PUT failed for ${s}/${r}: ${i.status}`),null}catch(c){return console.warn(`[artifacts] S3 PUT errored for ${s}/${r}: ${c.message}`),null}return{nodeName:s,filename:r,s3Key:p.s3Key,contentType:u,sizeBytes:n}}async function _e({sessionPath:o,executionId:e,apiUrl:t,apiKey:s}){let r={uploaded:[],skipped:[]};if(!o||!fe(o))return r;if(!t||!s||!e)return console.warn("[artifacts] uploader missing required input \u2014 skipping"),r;let a;try{a=z(o)}catch(i){return console.warn(`[artifacts] could not read session folder ${o}: ${i.message}`),r}let n=[];for(let i of a){let d=G(o,i),g;try{g=A(d)}catch{continue}if(!g.isDirectory()||i.startsWith(".")||i.startsWith("_"))continue;let P=J(d);for(let R of P){let E=ge(d,R).split(me).join("/"),w;try{w=A(R).size}catch{continue}if(w>W){r.skipped.push({nodeName:i,filename:E,reason:`size ${w} > ${W}`});continue}if(w===0){r.skipped.push({nodeName:i,filename:E,reason:"empty"});continue}n.push({apiUrl:t,apiKey:s,executionId:e,nodeName:i,filename:E,absolutePath:R,sizeBytes:w,contentType:Se(E)})}}if(n.length===0)return r;let u=4,p=n.slice(),c=Array.from({length:Math.min(u,p.length)},async()=>{for(;p.length;){let i=p.shift(),d=await Ee(i);d?r.uploaded.push(d):r.skipped.push({nodeName:i.nodeName,filename:i.filename,reason:"upload failed"})}});if(await Promise.all(c),r.uploaded.length>0)try{let i=await fetch(`${t}/executions/${e}/artifacts`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({files:r.uploaded})});if(!i.ok){let d=await i.text();console.warn(`[artifacts] record failed: ${i.status} ${d.slice(0,200)}`)}}catch(i){console.warn(`[artifacts] record errored: ${i.message}`)}return r}var W,we,he,Y=re(()=>{W=500*1024*1024,we=new Set([".DS_Store","Thumbs.db",".zibby-stop"]),he={".webm":"video/webm",".mp4":"video/mp4",".mov":"video/quicktime",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".txt":"text/plain",".md":"text/markdown",".html":"text/html",".csv":"text/csv",".log":"text/plain",".json":"application/json",".yaml":"application/yaml",".yml":"application/yaml",".pdf":"application/pdf",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip"}});import{mkdirSync as Z,writeFileSync as $e,existsSync as S,readFileSync as M}from"fs";import{join as m,dirname as Oe,resolve as q}from"path";import{pathToFileURL as U}from"url";import{execSync as Re,spawn as H}from"node:child_process";import{SQSClient as ae,SendMessageCommand as ce}from"@aws-sdk/client-sqs";var x=null;function le(){return x||(x=new ae({region:process.env.AWS_REGION||"ap-southeast-2"})),x}async function j(o,{status:e,error:t}){let{EXECUTION_ID:s,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:a,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:u}=o;if(!s)return;let p={executionId:s,...r&&{sqsAuthToken:r},status:e,...t&&{error:t},timestamp:new Date().toISOString()},c=a?"HTTP":n?"SQS":"NONE",i=JSON.stringify(p).length;console.log(`Sending final status: ${e} via ${c} (${(i/1024).toFixed(1)}KB)`);try{if(a)await pe(a,s,p,u);else if(n){let d=["completed","failed","insufficient_context","blocked"].includes(e)?"execution_completed":"progress_update";await de(n,s,p,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 ${c}`)}catch(d){console.error(`Failed to send final status (${e}) via ${c}:`),console.error(` Payload: ${(i/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 pe(o,e,t,s){let r=`${o}/${e}/progress`,a={"Content-Type":"application/json"};s&&(a.Authorization=`Bearer ${s}`);let n=await fetch(r,{method:"POST",headers:a,body:JSON.stringify(t)});if(!n.ok){let u=await n.text();throw new Error(`HTTP ${n.status}: ${u}`)}}async function de(o,e,t,s="progress_update"){let r=JSON.stringify(t),a=(r.length/1024).toFixed(1);r.length>256*1024&&console.error(`\u274C SQS message too large: ${a}KB (limit 256KB) for ${e} [${s}]`),await le().send(new ce({QueueUrl:o,MessageBody:r,MessageGroupId:e,MessageAttributes:{executionId:{DataType:"String",StringValue:e},messageType:{DataType:"String",StringValue:s}}}))}function K({workflowType:o,jobId:e,projectId:t,agentType:s,model:r,egressIp:a,egressKind:n}){let u="\u2500".repeat(60),p=`${s||"default"} (model: ${r||"auto"})`,c=["",u,` Workflow: ${o}`,` Job: ${e||"local"}`,` Project: ${t||"none"}`,` Agent: ${p}`];if(a||n){let i=a||"unknown",d=n||"static";c.push(` Egress: ${i} (${d})`)}return c.push(u),c.join(`
3
- `)}import"@zibby/core";var I=process.env.WORKSPACE||"/workspace";async function be(o,e){Z(e,{recursive:!0});let t=Date.now();console.log("[setup] Fetching bundle...");let s=setInterval(()=>{let a=((Date.now()-t)/1e3).toFixed(1);console.log(`[setup] still fetching (${a}s elapsed)`)},3e3);try{await new Promise((a,n)=>{let u=H("curl",["-fsSL",o],{stdio:["ignore","pipe","inherit"]}),p=H("tar",["-xzf","-","-C",e],{stdio:["pipe","inherit","inherit"]});u.stdout.pipe(p.stdin);let c,i,d=()=>{if(c!==void 0&&i!==void 0){if(c!==0)return n(new Error(`curl exited ${c}`));if(i!==0)return n(new Error(`tar exited ${i}`));a()}};u.on("close",g=>{c=g,d()}),p.on("close",g=>{i=g,d()}),u.on("error",n),p.on("error",n)})}finally{clearInterval(s)}let r=((Date.now()-t)/1e3).toFixed(1);return console.log(`[setup] Bundle extracted (${r}s)`),e}async function X(){let o=process.env.WORKFLOW_SOURCES_URL;if(!o)throw new Error("WORKFLOW_SOURCES_URL env var is required");let e=await fetch(o);if(!e.ok)throw new Error(`Failed to fetch sources: ${e.status} ${e.statusText}`);let t=await e.json();if(!t.sources||typeof t.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return t}function Pe(o){let e=o?.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 t of["claude","cursor","codex","gemini"])if(e[t])return t}return null}function Te(o,e){let t=q(e),s=0;for(let[r,a]of Object.entries(o)){let n=q(e,r);if(!n.startsWith(`${t}/`)&&n!==t){console.error(` \u26D4 Skipping unsafe path: ${r}`);continue}Z(Oe(n),{recursive:!0}),$e(n,a,"utf-8"),s++}return s}async function ke(){let o=process.env.ZIBBY_EGRESS_PROXY_URL,e=process.env.ZIBBY_EGRESS_TOKEN;if(!(!o||!e))try{let t=await import("undici"),s=new t.ProxyAgent({uri:o,token:`Bearer ${e}`});t.setGlobalDispatcher(s)}catch(t){console.warn(`[setup] Failed to install egress proxy dispatcher: ${t.message}`)}}async function xe(){if(process.env.ZIBBY_EGRESS_IP)return{ip:process.env.ZIBBY_EGRESS_IP,kind:"static"};try{let o=new AbortController,e=setTimeout(()=>o.abort(),1500),t=await fetch("https://api.ipify.org?format=json",{signal:o.signal});return clearTimeout(e),t.ok?{ip:(await t.json())?.ip||null,kind:"dynamic"}:{ip:null,kind:"dynamic"}}catch{return{ip:null,kind:"dynamic"}}}async function Ae(o,e){let t=m(o,"graph.mjs");if(!S(t))throw new Error(`graph.mjs not found at ${t}`);let s=await import(U(t).href),r=e?.entryClass,a=r&&s[r]||s.default||Object.values(s).find(n=>typeof n=="function"&&n.prototype?.buildGraph);if(!a)throw new Error("No WorkflowAgent class found in graph.mjs");return a}async function Je(){if(!process.env.NODE_PATH){process.env.NODE_PATH="/opt/zibby/packages";let l=await import("module");l.default._initPaths&&l.default._initPaths()}await ke();let{WORKFLOW_JOB_ID:o,WORKFLOW_TYPE:e,PROJECT_ID:t,AGENT_TYPE:s,MODEL:r}=process.env;e||(console.error("Missing WORKFLOW_TYPE env var"),process.exit(1));let a=process.env.WORKFLOW_BUNDLE_URL,n,u={},p,c;if(a){p=e,n=m(I,".zibby","workflows",p);try{await be(a,n);try{let l=await X();u=l.input||{},c=l.version}catch{}}catch(l){console.warn(`[setup] Bundle extract failed (${l.message}); falling back to source install`),n=null}}if(!n){let l=await X(),{sources:f,input:h,workflowType:_,version:y}=l;u=h||{},p=_||e,c=y,console.log(`[setup] Workflow v${c||"?"} (${Object.keys(f).length} files)`),n=m(I,".zibby","workflows",p);let b=Te(f,n);console.log(`[setup] Wrote ${b} files`),console.log("[setup] Installing dependencies...");try{Re("npm install --silent --no-audit --no-fund",{cwd:n,stdio:"inherit"}),console.log("[setup] Dependencies installed")}catch($){console.warn(`[setup] npm install failed: ${$.message}`)}}let i={},d=m(n,"workflow.json");S(d)&&(i=JSON.parse(M(d,"utf-8")));let g={},P=m(n,"zibby.config.json");if(S(P))try{g=JSON.parse(M(P,"utf-8")),console.log("[setup] Loaded user config from zibby.config.json")}catch(l){console.warn(`[setup] Failed to parse zibby.config.json: ${l.message} \u2014 falling back to defaults`)}let R=Pe(g)||s,E=await xe();console.log(K({workflowType:e,jobId:o,projectId:t,agentType:R,model:r,egressIp:E.ip,egressKind:E.kind}));let w=await Ae(n,i);console.log(`[setup] Loaded ${w.name}`);let O=[],C=m(n,"node_modules","@zibby","agent-workflow"),N=m(n,"node_modules","@zibby","core","node_modules","@zibby","agent-workflow");S(C)&&O.push({kind:"hoisted",path:C}),S(N)&&O.push({kind:"nested",path:N});let k=process.env.ZIBBY_RUN_DIAG==="1";if(k){let{readdirSync:l}=await import("fs");console.log(` [diag] @zibby/agent-workflow copies in bundle: ${O.length}`);for(let f of O)console.log(` [diag] ${f.kind}: ${f.path}`);try{let f=m(n,"node_modules","@zibby");S(f)&&console.log(` [diag] node_modules/@zibby/ contents: [${l(f).join(", ")}]`)}catch{}}let B=m(n,"node_modules","@zibby","core","dist","index.js");if(S(B)&&O.length>0)try{let l=await import(U(B).href),f=[l.AssistantStrategy,l.CursorAgentStrategy,l.ClaudeAgentStrategy,l.CodexAgentStrategy,l.GeminiAgentStrategy].filter(Boolean);for(let h of O){let _=m(h.path,"dist","index.js");if(!S(_))continue;let y=await import(U(_).href),b=k?y.listStrategies():null;for(let $ of f)try{y.registerStrategy(new $)}catch(ne){console.warn(` register ${$.name} into ${h.kind} failed: ${ne.message}`)}k&&console.log(` [diag] ${h.kind} registry: before=[${b.join(",")||"empty"}] after=[${y.listStrategies().join(",")||"empty"}]`)}console.log("[setup] Registered 5 agent strategies (assistant, cursor, claude, codex, gemini)")}catch(l){console.warn(`[setup] Failed to bridge strategies: ${l.message}`)}else console.warn("[setup] No @zibby/core or @zibby/agent-workflow in bundle \u2014 agent strategies may be unavailable");let V=Date.now(),F=new w({workflow:p||e}),ee=F.buildGraph(),te={input:u||{},cwd:I,runId:o||`run-${Date.now()}`,config:g};console.log("");let T;try{T=await ee.run(F,te)}catch(l){console.error(`
3
+ `)}import"@zibby/core";var I=process.env.WORKSPACE||"/workspace";async function be(o,e){Z(e,{recursive:!0});let t=Date.now();console.log("[setup] Fetching bundle...");let s=setInterval(()=>{let a=((Date.now()-t)/1e3).toFixed(1);console.log(`[setup] still fetching (${a}s elapsed)`)},3e3);try{await new Promise((a,n)=>{let u=H("curl",["-fsSL",o],{stdio:["ignore","pipe","inherit"]}),p=H("tar",["-xzf","-","-C",e],{stdio:["pipe","inherit","inherit"]});u.stdout.pipe(p.stdin);let c,i,d=()=>{if(c!==void 0&&i!==void 0){if(c!==0)return n(new Error(`curl exited ${c}`));if(i!==0)return n(new Error(`tar exited ${i}`));a()}};u.on("close",g=>{c=g,d()}),p.on("close",g=>{i=g,d()}),u.on("error",n),p.on("error",n)})}finally{clearInterval(s)}let r=((Date.now()-t)/1e3).toFixed(1);return console.log(`[setup] Bundle extracted (${r}s)`),e}async function X(){let o=process.env.WORKFLOW_SOURCES_URL;if(!o)throw new Error("WORKFLOW_SOURCES_URL env var is required");let e=await fetch(o);if(!e.ok)throw new Error(`Failed to fetch sources: ${e.status} ${e.statusText}`);let t=await e.json();if(!t.sources||typeof t.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return t}function Pe(o){let e=o?.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 t of["claude","cursor","codex","gemini"])if(e[t])return t}return null}function Te(o,e){let t=q(e),s=0;for(let[r,a]of Object.entries(o)){let n=q(e,r);if(!n.startsWith(`${t}/`)&&n!==t){console.error(` \u26D4 Skipping unsafe path: ${r}`);continue}Z(Oe(n),{recursive:!0}),$e(n,a,"utf-8"),s++}return s}async function ke(){let o=process.env.ZIBBY_EGRESS_PROXY_URL,e=process.env.ZIBBY_EGRESS_TOKEN;if(!(!o||!e))try{let t=await import("undici"),s=new t.ProxyAgent({uri:o,token:`Bearer ${e}`});t.setGlobalDispatcher(s)}catch(t){console.warn(`[setup] Failed to install egress proxy dispatcher: ${t.message}`)}}async function xe(){if(process.env.ZIBBY_EGRESS_IP)return{ip:process.env.ZIBBY_EGRESS_IP,kind:"static"};try{let o=new AbortController,e=setTimeout(()=>o.abort(),1500),t=await fetch("https://api.ipify.org?format=json",{signal:o.signal});return clearTimeout(e),t.ok?{ip:(await t.json())?.ip||null,kind:"dynamic"}:{ip:null,kind:"dynamic"}}catch{return{ip:null,kind:"dynamic"}}}async function Ae(o,e){let t=m(o,"graph.mjs");if(!S(t))throw new Error(`graph.mjs not found at ${t}`);let s=await import(U(t).href),r=e?.entryClass,a=r&&s[r]||s.default||Object.values(s).find(n=>typeof n=="function"&&n.prototype?.buildGraph);if(!a)throw new Error("No WorkflowAgent class found in graph.mjs");return a}async function Je(){if(!process.env.NODE_PATH){process.env.NODE_PATH="/opt/zibby/packages";let l=await import("module");l.default._initPaths&&l.default._initPaths()}await ke();let{WORKFLOW_JOB_ID:o,WORKFLOW_TYPE:e,PROJECT_ID:t,AGENT_TYPE:s,MODEL:r}=process.env;e||(console.error("Missing WORKFLOW_TYPE env var"),process.exit(1));let a=process.env.WORKFLOW_BUNDLE_URL,n,u={},p,c;if(a){p=e,n=m(I,".zibby","workflows",p);try{await be(a,n);try{let l=await X();u=l.input||{},c=l.version}catch{}}catch(l){console.warn(`[setup] Bundle extract failed (${l.message}); falling back to source install`),n=null}}if(!n){let l=await X(),{sources:f,input:h,workflowType:_,version:y}=l;u=h||{},p=_||e,c=y,console.log(`[setup] Workflow v${c||"?"} (${Object.keys(f).length} files)`),n=m(I,".zibby","workflows",p);let b=Te(f,n);console.log(`[setup] Wrote ${b} files`),console.log("[setup] Installing dependencies...");try{Re("npm install --silent --no-audit --no-fund",{cwd:n,stdio:"inherit"}),console.log("[setup] Dependencies installed")}catch($){console.warn(`[setup] npm install failed: ${$.message}`)}}let i={},d=m(n,"workflow.json");S(d)&&(i=JSON.parse(M(d,"utf-8")));let g={},P=m(n,"zibby.config.json");if(S(P))try{g=JSON.parse(M(P,"utf-8")),console.log("[setup] Loaded user config from zibby.config.json")}catch(l){console.warn(`[setup] Failed to parse zibby.config.json: ${l.message} \u2014 falling back to defaults`)}let R=Pe(g)||s,E=await xe();console.log(K({workflowType:e,jobId:o,projectId:t,agentType:R,model:r,egressIp:E.ip,egressKind:E.kind}));let w=await Ae(n,i);console.log(`[setup] Loaded ${w.name}`);let O=[],C=m(n,"node_modules","@zibby","agent-workflow"),N=m(n,"node_modules","@zibby","core","node_modules","@zibby","agent-workflow");S(C)&&O.push({kind:"hoisted",path:C}),S(N)&&O.push({kind:"nested",path:N});let k=process.env.ZIBBY_RUN_DIAG==="1";if(k){let{readdirSync:l}=await import("fs");console.log(` [diag] @zibby/agent-workflow copies in bundle: ${O.length}`);for(let f of O)console.log(` [diag] ${f.kind}: ${f.path}`);try{let f=m(n,"node_modules","@zibby");S(f)&&console.log(` [diag] node_modules/@zibby/ contents: [${l(f).join(", ")}]`)}catch{}}let B=m(n,"node_modules","@zibby","core","dist","index.js");if(S(B)&&O.length>0)try{let l=await import(U(B).href),f=[l.AssistantStrategy,l.CursorAgentStrategy,l.ClaudeAgentStrategy,l.CodexAgentStrategy,l.GeminiAgentStrategy].filter(Boolean);for(let h of O){let _=m(h.path,"dist","index.js");if(!S(_))continue;let y=await import(U(_).href),b=k?y.listStrategies():null;for(let $ of f)try{y.registerStrategy(new $)}catch(ne){console.warn(` register ${$.name} into ${h.kind} failed: ${ne.message}`)}k&&console.log(` [diag] ${h.kind} registry: before=[${b.join(",")||"empty"}] after=[${y.listStrategies().join(",")||"empty"}]`)}console.log("[setup] Registered 5 agent strategies (assistant, cursor, claude, codex, gemini)")}catch(l){console.warn(`[setup] Failed to bridge strategies: ${l.message}`)}else console.warn("[setup] No @zibby/core or @zibby/agent-workflow in bundle \u2014 agent strategies may be unavailable");let V=Date.now(),F=new w({workflow:p||e}),ee=F.buildGraph(),te={...u||{},cwd:I,runId:o||`run-${Date.now()}`,config:g,input:u||{}};console.log("");let T;try{T=await ee.run(F,te)}catch(l){console.error(`
4
4
  Workflow execution failed: ${l.message}`),console.error(l.stack),await v("failed",l.message),process.exit(1)}let L=((Date.now()-V)/1e3).toFixed(1),oe=T?.success!==!1,D=p||e;if(process.env.UPLOAD_ARTIFACTS!=="0"){let l=T?.state?.sessionPath,f=process.env.PROGRESS_API_URL||process.env.ZIBBY_API_BASE,h=process.env.PROJECT_API_TOKEN,_=process.env.WORKFLOW_JOB_ID;if(l&&f&&h&&_)try{let{uploadSessionArtifacts:y}=await Promise.resolve().then(()=>(Y(),Q)),{uploaded:b,skipped:$}=await y({sessionPath:l,executionId:_,apiUrl:f,apiKey:h});console.log(`[artifacts] uploaded ${b.length} file(s)${$.length?`, skipped ${$.length}`:""}`)}catch(y){console.warn(`[artifacts] uploader threw: ${y.message}`)}else console.log("[artifacts] skipping upload \u2014 sessionPath/apiUrl/apiKey/executionId missing")}oe?(console.log(`
5
5
  [done] ${D} completed in ${L}s`),await v("completed")):(console.error(`
6
6
  [done] ${D} failed after ${L}s`),await v("failed",T?.error||"Workflow execution failed"),process.exit(1))}async function v(o,e=null){let t={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(t.EXECUTION_ID)try{await j(t,{status:o,...e&&{error:e}})}catch(s){console.error(`\u26A0\uFE0F Failed to report status: ${s.message}`)}}export{Pe as resolveAgentFromConfig,Je as runWorkflowCommand};
@@ -1,4 +1,4 @@
1
- var j=Object.defineProperty;var I=(n,t)=>()=>(n&&(t=n(n=0)),t);var K=(n,t)=>{for(var o in t)j(n,o,{get:t[o],enumerable:!0})};var N={};K(N,{_resetLoaderCacheForTests:()=>G,loadCredentialsIntoEnv:()=>Y});import b from"node:fs";import R from"node:path";import W from"node:os";async function k(){if(!(process.env.__ZIBBY_CLAUDE_PLAN||process.platform!=="darwin"||!(process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_AUTH_TOKEN)))try{let{execSync:t}=await import("node:child_process"),o=t('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(o){let f=JSON.parse(o)?.claudeAiOauth?.subscriptionType;f&&(process.env.__ZIBBY_CLAUDE_PLAN=f)}}catch{}}function F(n){try{if(!b.existsSync(n))return{};let t=b.readFileSync(n,"utf-8"),o=JSON.parse(t);return o&&o.agentKeys&&typeof o.agentKeys=="object"?o.agentKeys:{}}catch{return{}}}async function Y(n={}){let{verbose:t=!1,force:o=!1,configPath:c}=n;if(h&&!o)return w;if(!!(process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_API_KEY_POOL||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.ANTHROPIC_API_KEY||process.env.ANTHROPIC_AUTH_TOKEN))return await k(),h=!0,w={oauthCount:0,apiCount:0,source:"cloud-env"},t&&console.log("[credentials-loader] env vars already set \u2014 skipping local discovery"),w;let l=c||R.join(W.homedir(),".zibby","config.json"),a=F(l),i="none",s=0,g=0;for(let r of z)a[r]&&!process.env[r]&&(process.env[r]=String(a[r]).trim(),i="config.json",r.endsWith("_POOL")?s+=String(a[r]).split(",").filter(p=>p.trim()).length:s+=1);for(let r of B)a[r]&&!process.env[r]&&(process.env[r]=String(a[r]).trim(),i="config.json",r.endsWith("_POOL")?g+=String(a[r]).split(",").filter(p=>p.trim()).length:g+=1);return await k(),h=!0,w={oauthCount:s,apiCount:g,source:i},t&&s+g>0&&console.log(`[credentials-loader] loaded ${s} OAuth + ${g} API from ${i} (~/.zibby/config.json)`),w}function G(){h=!1,w=null}var h,w,z,B,$=I(()=>{h=!1,w=null,z=["CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_OAUTH_TOKEN_POOL","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_AUTH_TOKEN_POOL"],B=["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_POOL"]});import{existsSync as _}from"fs";import{readFile as J}from"fs/promises";import{join as C}from"path";import{pathToFileURL as M}from"url";import e from"chalk";import Z from"ora";import{existsSync as H}from"fs";import{join as D}from"path";import{pathToFileURL as x}from"url";async function P(n){let t=D(n,".zibby.config.mjs");if(!H(t))throw new Error(".zibby.config.mjs not found");try{let o=await import(x(t).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}var q=3848;async function V(n){try{let t=await P(n);return{userConfig:t,workflowsBasePath:t?.paths?.workflows||".zibby/workflows"}}catch{return{userConfig:null,workflowsBasePath:".zibby/workflows"}}}async function X(n,t,o){let c=C(n,"graph.mjs");if(!_(c))throw new Error(`graph.mjs not found in ${o}/${t}/`);let f=await Q(n,t),l=await import(M(c).href),a=f.entryClass,i=a&&l[a]||l.default||Object.values(l).find(s=>typeof s=="function"&&s.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:i,manifest:f}}async function Q(n,t){let o=C(n,"workflow.json");if(!_(o))return{name:t,triggers:{api:!0}};let c=await J(o,"utf-8");return JSON.parse(c)}async function yo(n,t){n||(console.log(e.red(`
1
+ var j=Object.defineProperty;var I=(n,t)=>()=>(n&&(t=n(n=0)),t);var K=(n,t)=>{for(var o in t)j(n,o,{get:t[o],enumerable:!0})};var N={};K(N,{_resetLoaderCacheForTests:()=>G,loadCredentialsIntoEnv:()=>Y});import b from"node:fs";import R from"node:path";import W from"node:os";async function k(){if(!(process.env.__ZIBBY_CLAUDE_PLAN||process.platform!=="darwin"||!(process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_AUTH_TOKEN)))try{let{execSync:t}=await import("node:child_process"),o=t('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(o){let f=JSON.parse(o)?.claudeAiOauth?.subscriptionType;f&&(process.env.__ZIBBY_CLAUDE_PLAN=f)}}catch{}}function z(n){try{if(!b.existsSync(n))return{};let t=b.readFileSync(n,"utf-8"),o=JSON.parse(t);return o&&o.agentKeys&&typeof o.agentKeys=="object"?o.agentKeys:{}}catch{return{}}}async function Y(n={}){let{verbose:t=!1,force:o=!1,configPath:c}=n;if(h&&!o)return w;if(!!(process.env.CLAUDE_CODE_OAUTH_TOKEN_POOL||process.env.ANTHROPIC_API_KEY_POOL||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.ANTHROPIC_API_KEY||process.env.ANTHROPIC_AUTH_TOKEN))return await k(),h=!0,w={oauthCount:0,apiCount:0,source:"cloud-env"},t&&console.log("[credentials-loader] env vars already set \u2014 skipping local discovery"),w;let l=c||R.join(W.homedir(),".zibby","config.json"),a=z(l),i="none",s=0,g=0;for(let r of B)a[r]&&!process.env[r]&&(process.env[r]=String(a[r]).trim(),i="config.json",r.endsWith("_POOL")?s+=String(a[r]).split(",").filter(p=>p.trim()).length:s+=1);for(let r of F)a[r]&&!process.env[r]&&(process.env[r]=String(a[r]).trim(),i="config.json",r.endsWith("_POOL")?g+=String(a[r]).split(",").filter(p=>p.trim()).length:g+=1);return await k(),h=!0,w={oauthCount:s,apiCount:g,source:i},t&&s+g>0&&console.log(`[credentials-loader] loaded ${s} OAuth + ${g} API from ${i} (~/.zibby/config.json)`),w}function G(){h=!1,w=null}var h,w,B,F,$=I(()=>{h=!1,w=null,B=["CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_OAUTH_TOKEN_POOL","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_AUTH_TOKEN_POOL"],F=["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_POOL"]});import{existsSync as _}from"fs";import{readFile as J}from"fs/promises";import{join as C}from"path";import{pathToFileURL as M}from"url";import e from"chalk";import Z from"ora";import{existsSync as H}from"fs";import{join as D}from"path";import{pathToFileURL as x}from"url";async function P(n){let t=D(n,".zibby.config.mjs");if(!H(t))throw new Error(".zibby.config.mjs not found");try{let o=await import(x(t).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}var q=3848;async function V(n){try{let t=await P(n);return{userConfig:t,workflowsBasePath:t?.paths?.workflows||"workflows"}}catch{return{userConfig:null,workflowsBasePath:"workflows"}}}async function X(n,t,o){let c=C(n,"graph.mjs");if(!_(c))throw new Error(`graph.mjs not found in ${o}/${t}/`);let f=await Q(n,t),l=await import(M(c).href),a=f.entryClass,i=a&&l[a]||l.default||Object.values(l).find(s=>typeof s=="function"&&s.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:i,manifest:f}}async function Q(n,t){let o=C(n,"workflow.json");if(!_(o))return{name:t,triggers:{api:!0}};let c=await J(o,"utf-8");return JSON.parse(c)}async function yo(n,t){n||(console.log(e.red(`
2
2
  Workflow name is required`)),console.log(e.gray(" Usage: zibby workflow start <workflow-name>")),console.log(e.gray(` Example: zibby workflow start ticket-triage
3
3
  `)),process.exit(1));let o=n.toLowerCase(),c=process.cwd();try{let{loadCredentialsIntoEnv:d}=await Promise.resolve().then(()=>($(),N));await d({verbose:!!process.env.ZIBBY_DEBUG})}catch{}let{userConfig:f,workflowsBasePath:l}=await V(c),a=C(c,l,o);_(a)||(console.log(e.red(`
4
4
  Workflow not found: ${l}/${o}/`)),console.log(e.gray(" Create one first:")),console.log(e.cyan(` zibby workflow new ${o}
@@ -1,63 +1,63 @@
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(`
1
+ var K=Object.defineProperty;var q=(e,o)=>()=>(e&&(o=e(e=0)),o);var H=(e,o)=>{for(var t in o)K(e,t,{get:o[t],enumerable:!0})};var W={};H(W,{logsCommand:()=>me,parseSseChunk:()=>Y,runReconnectLoop:()=>M,sseBackoffMs:()=>J});import i from"chalk";import{readFileSync as ne,existsSync as re,writeSync as se}from"fs";import{homedir as ie}from"os";import{join as le}from"path";async function ce(e){return T||(process.env.ZIBBY_SSE_ENDPOINT?(T=process.env.ZIBBY_SSE_ENDPOINT,T):(T=ae,T))}function fe(e){let o=le(ie(),".zibby","config.json");re(o)||(console.log(i.red(`
2
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(`
3
+ `)),process.exit(1));let t;try{t=JSON.parse(ne(o,"utf-8"))}catch{console.log(i.red(`
4
4
  Config file corrupt`)),console.log(i.gray(` Run: zibby login
5
5
  `)),process.exit(1)}let n=t.sessionToken;n||(console.log(i.red(`
6
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(`
7
+ `)),process.exit(1));let s=e.project;return{token:n,projectId:s}}function B(e){return new Date(e).toISOString().replace("T"," ").replace("Z","")}async function F(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 pe(e,o,t,n){return e||(console.log(i.red(`
8
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(`
9
+ `)),process.exit(1)),e}function Y(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 d=f.slice(6).trim();if(d==="log")continue;if(d==="status"){let p=n[c+1];if(p&&p.startsWith("data:"))try{let g=JSON.parse(p.slice(5).trim());g.status==="new_execution"?l.push({type:"newExecution",executionId:g.executionId,taskId:g.taskId}):g.status==="waiting"&&l.push({type:"waiting"})}catch{}continue}if(d==="complete"){l.push({type:"complete"});continue}if(d==="error"){let p=n[c+1];if(p&&p.startsWith("data:"))try{if(JSON.parse(p.slice(5).trim()).error==="No executions found for workflow"){r={type:"notFound"};break}}catch{}r={type:"failed"};break}continue}if(f.startsWith("data:")){let d=f.slice(5).trim();if(!d)continue;try{let p=JSON.parse(d);p.timestamp&&p.message&&l.push({type:"log",timestamp:p.timestamp,message:p.message,taskId:p.taskId})}catch{}}}}return{actions:l,remainder:s,lastEventId:a,returnSignal:r}}async function ue({token:e,executionId:o,sseEndpoint:t,stopped:n}){let s=null;try{let h=function(){let b=Array.from(y.entries()).slice(0,p);y.clear();for(let[I,w]of b)y.set(I,w);u=new Set(Array.from(y.values()).map(I=>I.taskId).filter(Boolean));for(let I of[...m.keys()])y.has(I)||m.delete(I)},E=function($){for(let[b,I]of y)if(I.taskId===$)return b;return null},v=function($){let b=y.get($);!b||b.headerPrinted||(console.log(i.cyan(`
11
+ \u250C\u2500 Execution: ${b.shortId} (task: ${b.taskSuffix})`)),console.log(i.cyan(` \u2514\u2500 Streaming logs...
12
+ `)),b.headerPrinted=!0)},_=function($){let b=i.gray(B($.timestamp)),I=$.taskId?i.gray(`(${$.taskId.slice(-8)}) `):"";console.log(`${b} ${I}${$.message.replace(/\n$/,"")}`)},R=function(){if(!k)return;k=!1,x&&(clearTimeout(x),x=null);let $=Array.from(y.entries()).reverse();for(let[b]of $){let I=m.get(b);if(!(!I||I.length===0)){v(b);for(let w of I)_(w)}}m.clear()},P=function(){k&&(x&&clearTimeout(x),x=setTimeout(R,g))},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="",d=!1,p=Number(process.env.ZIBBY_LOGS_HISTORY_LIMIT)||10,g=Number(process.env.ZIBBY_LOGS_REPLAY_TIMEOUT_MS)||3e3,y=new Map,u=new Set,m=new Map,k=!0,x=null;for(P();!n.value;){let{done:$,value:b}=await r.read();if($)break;let I=Y(f,c.decode(b,{stream:!0}));f=I.remainder,I.lastEventId&&(s=I.lastEventId);for(let w of I.actions)switch(w.type){case"newExecution":{let S=`${w.executionId.slice(0,8)}...${w.executionId.slice(-4)}`,N=w.taskId?w.taskId.slice(-8):"pending";y.set(w.executionId,{shortId:S,taskSuffix:N,taskId:w.taskId||null,headerPrinted:!1}),m.has(w.executionId)||m.set(w.executionId,[]),h(),P();break}case"waiting":R(),console.log(i.gray(`
13
+ Waiting for next execution...`));break;case"complete":R(),d=!0;break;case"log":{if(w.taskId&&u.size>0&&!u.has(w.taskId))break;if(k){let S=w.taskId?E(w.taskId):null;if(S){let N=m.get(S)||[];N.push(w),m.set(S,N),P()}else _(w)}else{if(w.taskId){let S=E(w.taskId);S&&v(S)}_(w)}break}}if(I.returnSignal)return I.returnSignal.type==="notFound"?{notFound:!0}:{failed:!0}}return R(),{completed:d}}catch(l){if(l.name==="AbortError")return{aborted:!0};throw l}}function J(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 M({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=J,notFoundPollMs:r=5e3}){let c=0,f=!1;for(;!o.value;){let d;try{d=await e(),c=0}catch(p){if(p.name==="AbortError"||o.value)return{reason:"aborted"};if(f||(n.error(` SSE Error: ${p.message}`),t&&n.gray(" Reconnecting..."),f=!0),!t)return l("error")??{reason:"error"};let g=a(c);c++,await s(g);continue}if(d.aborted||o.value)return{reason:"aborted"};if(d.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
14
  No executions found for this workflow. Trigger the workflow first.
15
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,`
16
+ `),f=!1),d.failed)return n.red(`
17
+ Execution failed.`),t?{reason:"failed"}:l("failed")??{reason:"failed"};if(d.completed)return l("completed")??{reason:"completed"};if(!t)return{reason:"disconnected"}}return{reason:"stopped"}}async function de({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 ce(e);if(!s)return console.log(i.yellow(` SSE endpoint not configured, using CloudWatch polling...
19
+ `)),Z({token:e,projectId:null,jobId:o,follow:t,limit:1e5});let l={value:!1},a=()=>{l.value=!0;try{se(2,`
20
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(`
21
+ `)}catch{}process.exit(0)};process.prependListener("SIGINT",a),process.prependListener("SIGTERM",a),await M({attemptStream:()=>ue({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 Z({token:e,projectId:o,jobId:t,follow:n,limit:s}){let l=o?`${A}/logs/${o}/${t}`:`${A}/job/${t}`,a=null,r=0,c=new Set,f=!1,d=0,p=5,g=()=>{f=!0,console.log(i.gray(`
22
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(`
23
+ `)),process.exit(0)};for(process.on("SIGINT",g),process.on("SIGTERM",g),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 u=await F(`${l}?${y}`,e);d=0,u.message&&u.lines?.length===0&&r===0&&console.log(i.gray(` ${u.message}`)),u.status==="starting"&&u.lines?.length===0&&r===0&&console.log(i.gray(" Container starting..."));for(let h of u.lines||[]){let E=`${h.timestamp}:${h.message}`;if(c.has(E))continue;c.add(E);let v=i.gray(B(h.timestamp)),_=u.taskId?i.gray(`(${u.taskId.slice(-8)}) `):"";console.log(`${v} ${_}${h.message.replace(/\n$/,"")}`)}if(r=u.lines?.length>0?0:r+1,a=u.nextForwardToken||null,u.status==="completed"||u.status==="failed"){let h=u.status==="completed"?i.green:i.red;console.log(h(`
25
+ Job ${u.status}.`)),process.exit(u.status==="completed"?0:1)}if(!n){u.status&&console.log(i.gray(`
26
+ Status: ${u.status}`));break}let x=u.lines?.length>0?500:r>5?5e3:2e3;await new Promise(h=>setTimeout(h,x))}catch(y){if(y.name==="AbortError")break;y.message.match(/API (400|401|403|404):/)&&(console.error(i.red(`
27
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(`
28
+ `)),process.exit(1)),d++,console.error(i.red(` Error: ${y.message}`)),d>=p&&(console.error(i.red(`
29
+ Too many consecutive errors (${p}). Stopping.
30
+ `)),process.exit(1)),n||process.exit(1),await new Promise(m=>setTimeout(m,3e3))}}async function ge({token:e,projectId:o,workflow:t,follow:n,limit:s}){let l=`${A}/all/${o}`,a=null,r=0,c=new Set,f=null,d=!1,p=0,g=5,y=()=>{d=!0,console.log(i.gray(`
31
31
  Stopped tailing.
32
32
  `)),process.exit(0)};for(process.on("SIGINT",y),process.on("SIGTERM",y),console.log(i.gray(`
33
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(`
34
+ `):"");!d;)try{let u=new URLSearchParams({workflow:t,limit:String(s)});a&&u.set("nextToken",a);let m=await F(`${l}?${u}`,e);p=0,m.message&&m.lines?.length===0&&r===0&&console.log(i.gray(` ${m.message}`));for(let h of m.lines||[]){let E=`${h.timestamp}:${h.jobId}:${h.message}`;if(c.has(E))continue;c.add(E),h.jobId!==f&&(f!==null&&console.log(""),console.log(i.dim(` \u2500\u2500 ${h.jobId} \u2500\u2500`)),f=h.jobId);let v=i.gray(B(h.timestamp));console.log(`${v} ${h.message.replace(/\n$/,"")}`)}if(r=m.lines?.length>0?0:r+1,a=m.nextToken||null,!n){a&&console.log(i.gray(`
35
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(`
36
+ No running jobs. All caught up.`));break}let x=m.lines?.length>0?500:r>5?5e3:2e3;await new Promise(h=>setTimeout(h,x))}catch(u){if(u.name==="AbortError")break;u.message.match(/API (400|401|403|404):/)&&(console.error(i.red(`
37
+ ${u.message}
38
+ `)),process.exit(1)),p++,console.error(i.red(` Error: ${u.message}`)),p>=g&&(console.error(i.red(`
39
+ Too many consecutive errors (${g}). Stopping.
40
+ `)),process.exit(1)),n||process.exit(1),await new Promise(k=>setTimeout(k,3e3))}}async function me(e,o){let{token:t,projectId:n}=fe(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
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(`
42
+ `)),process.exit(1)),ge({token:t,projectId:n,workflow:r,follow:s,limit:l})}let a=await pe(e,o,t,n);return s?de({token:t,jobId:a,follow:s,projectId:n}):Z({token:t,projectId:n,jobId:a,follow:!1,limit:l})}var A,ae,T,G=q(()=>{A="https://logs.workflows.zibby.app",ae="https://logs-stream.zibby.app/",T=null});import C from"ora";import{select as V}from"@inquirer/prompts";import{readFileSync as ye,existsSync as we}from"fs";import{homedir as he}from"os";import{join as Ie}from"path";var U={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 j(){let e;if(process.env.ZIBBY_API_URL)e=process.env.ZIBBY_API_URL;else{let o=process.env.ZIBBY_ENV||"prod";U[o]?e=U[o].apiUrl:e=U.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)`),U.prod.apiUrl):e}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${e}`),U.prod.apiUrl}}var X=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function L(e){return e?X.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 Q,readFileSync as ee}from"fs";import{resolve as oe}from"path";function O(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}function z(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=O(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 te(e){let o=oe(e);Q(o)||(console.log(`
43
43
  Error: --input-file not found: ${e}
44
- `),process.exit(1));try{return JSON.parse(G(o,"utf-8"))}catch(t){console.log(`
44
+ `),process.exit(1));try{return JSON.parse(ee(o,"utf-8"))}catch(t){console.log(`
45
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(`
46
+ `),process.exit(1)}}function D(e){let o={};if(e.inputFile&&(o={...te(e.inputFile)}),e.input)try{o={...o,...JSON.parse(e.input)}}catch(t){console.log(`
47
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(`
48
+ `),process.exit(1)}return e.param?.length&&(o={...o,...z(e.param)}),o}function be(){let e=Ie(he(),".zibby","config.json");if(we(e))try{let t=JSON.parse(ye(e,"utf-8"));if(t.sessionToken)return t.sessionToken}catch{}let o=process.env.ZIBBY_API_KEY;if(o)return o;console.log(`
49
49
  Not authenticated`),console.log(" Run: zibby login"),console.log(` OR set ZIBBY_API_KEY env var (for CI/CD)
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(`
50
+ `),process.exit(1)}async function $e(e){let o=j(),t=C("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 V({message:"Select a project:",choices:l})}catch(n){t.fail(`Error: ${n.message}`),process.exit(1)}}async function ke(e,o){let t=j(),n=C("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 V({message:"Select a workflow to trigger:",choices:a})}catch(s){n.fail(`Error: ${s.message}`),process.exit(1)}}async function Fe(e,o={}){let t=L(e);t.ok||(console.log(`
51
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(`
52
+ `),process.exit(1));let n=be(),s=o.project||process.env.ZIBBY_PROJECT_ID,l;if(e){let c=j();try{let f=await fetch(`${c}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});if(f.ok){let p=(await f.json()).projects||[];for(let g of p){let y=await fetch(`${c}/projects/${g.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});if(y.ok){let m=(await y.json()).find(k=>k.uuid===e);if(m){s=g.projectId,l=m.workflowType||m.name,console.log(`
53
53
  \u2713 Found workflow "${l}" (UUID: ${e})
54
54
  `);break}}}(!l||l===e)&&(console.log(`
55
55
  Error: Workflow with UUID "${e}" not found`),console.log(` Check: zibby workflow list
56
56
  `),process.exit(1))}}catch(f){console.log(`
57
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(`
58
+ `),process.exit(1)}}s||(console.log(""),s=await $e(n)),l||(console.log(""),l=await ke(s,n));let a=D(o);if(console.log(`
59
59
  Triggering Workflow
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};
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=C("Triggering workflow execution...").start();try{let c=j(),f={input:a};o.idempotencyKey&&(f.idempotencyKey=o.idempotencyKey);let d=await fetch(`${c}/projects/${s}/workflows/${l}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(f)});if(!d.ok){let g=await d.json().catch(()=>({}));d.status===429&&(r.fail("Quota exceeded"),console.log(`
61
+ Your workflow execution quota has been exceeded`),g.quotaInfo&&(console.log(` Used: ${g.quotaInfo.used}/${g.quotaInfo.limit} executions`),console.log(` Plan: ${g.quotaInfo.planId}`),g.quotaInfo.periodEnd&&console.log(` Resets: ${new Date(g.quotaInfo.periodEnd).toLocaleDateString()}`)),console.log(""),process.exit(1)),r.fail("Trigger failed"),console.log(` Error: ${g.message||d.statusText}
62
+ `),process.exit(1)}let p=await d.json();if(r.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${p.jobId}`),console.log(` Status: ${p.status}`),console.log(` Version: ${p.version}`),console.log(` Triggered: ${new Date(p.triggeredAt).toLocaleString()}`),console.log(""),o.follow){console.log(" Streaming logs (Ctrl+C to stop)..."),console.log("");let{logsCommand:g}=await Promise.resolve().then(()=>(G(),W));return g(p.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{O as coerceValue,z as parseParams,D as resolveInput,Fe as triggerWorkflowCommand};
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
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/deploy-skip-unchanged.test.js test/deploy-warm-flag.test.js test/deploy-402-formatter.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/template-resolver.test.js test/workflow-new-template.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",
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/deploy-402-formatter.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/template-resolver.test.js test/workflow-new-template.test.js test/runner-input-state-shape.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 .",