@zibby/cli 0.4.1 → 0.4.2
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,2 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import i from"chalk";import B from"inquirer";import{execSync as M}from"node:child_process";import{existsSync as T,readFileSync as C,writeFileSync as W,chmodSync as q,unlinkSync as Q}from"node:fs";import{homedir as Z,tmpdir as X}from"node:os";import{join as h}from"node:path";import{randomBytes as ee}from"node:crypto";import{existsSync as R,readFileSync as j,writeFileSync as pe,mkdirSync as ye}from"fs";import{join as D}from"path";import{homedir as G}from"os";var m={cursor:{envVar:"CURSOR_API_KEY",label:"Cursor API Key",url:"https://cursor.com/settings"},claude:{envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com/settings/keys"},codex:{envVar:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com/api-keys"},gemini:{envVar:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com/app/apikey"}};function H(){return D(G(),".zibby","config.json")}function O(){try{let e=H();return R(e)?JSON.parse(j(e,"utf-8")):{}}catch{return{}}}import{readFileSync as V,existsSync as z}from"fs";import F from"dotenv";var K=/^[A-Z_][A-Z0-9_]*$/;function J(e){return typeof e=="string"&&K.test(e)}function w(e){if(!Array.isArray(e)||e.length===0)return{};let t={};for(let n of e){if(!z(n))throw new Error(`--env file not found: ${n}`);let r=F.parse(V(n,"utf-8"));for(let[o,s]of Object.entries(r)){if(!J(o))throw new Error(`Invalid env var name "${o}" in ${n} \u2014 must match ${K} (uppercase letters, digits, underscores; can't start with a digit)`);t[o]=s}}return t}function b(e,t,n){let r=String(e).replace(/\/+$/,"");return n?`${r}/workflows/${t}/env/${encodeURIComponent(n)}`:`${r}/workflows/${t}/env`}var te={claude:["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"],cursor:["CURSOR_API_KEY"],codex:["OPENAI_API_KEY"],gemini:["GOOGLE_API_KEY"]};function re(){if(process.platform==="darwin")try{let e=M('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(e){let t=JSON.parse(e);if(t?.claudeAiOauth?.accessToken)return t.claudeAiOauth}}catch{}try{let e=h(Z(),".claude",".credentials.json");return T(e)&&JSON.parse(C(e,"utf-8"))?.claudeAiOauth||null}catch{return null}}var ne={claude:[{localVar:"ANTHROPIC_API_KEY",uploadAs:"ANTHROPIC_API_KEY",kind:"api"},{localVar:"CLAUDE_CODE_OAUTH_TOKEN",uploadAs:"CLAUDE_CODE_OAUTH_TOKEN",kind:"oauth"}],cursor:[{localVar:"CURSOR_API_KEY",uploadAs:"CURSOR_API_KEY",kind:"api"}],codex:[{localVar:"OPENAI_API_KEY",uploadAs:"OPENAI_API_KEY",kind:"api"}],gemini:[{localVar:"GEMINI_API_KEY",uploadAs:"GOOGLE_API_KEY",kind:"api"},{localVar:"GOOGLE_API_KEY",uploadAs:"GOOGLE_API_KEY",kind:"api"}]};function oe(e){let t=N(e);if(!t)return null;let n=e?.agent;if(!n||typeof n!="object")return null;let r=n[t];if(r&&typeof r=="object"&&typeof r.auth=="string"){let o=r.auth.toLowerCase();if(o==="oauth"||o==="api")return o}return null}function N(e){if(!e||typeof e!="object")return null;let t=e.agent;if(!t)return null;if(typeof t=="string")return m[t]?t:null;if(typeof t=="object"){if(typeof t.provider=="string"&&m[t.provider])return t.provider;for(let n of Object.keys(t))if(m[n])return n}return null}function se(e){if(!e)return null;let t=h(e,".zibby-deploy.json");if(!T(t))return null;try{let n=JSON.parse(C(t,"utf-8"));if(typeof n?.uuid=="string"&&n.uuid)return n.uuid}catch{}return null}function ie(e,t,n){let o=(ne[e]||[]).slice().sort((s,a)=>n&&s.kind===n&&a.kind!==n?-1:n&&a.kind===n&&s.kind!==n?1:0);for(let s of o){let a=t?.[s.localVar];if(typeof a=="string"&&a.trim())return{...s,value:a.trim()}}return null}function ae(e,t,{readConfig:n=O}={}){let r=n()||{},o=r.agentKeys&&typeof r.agentKeys=="object"?r.agentKeys:{};return ie(e,o,t)}async function ce({apiUrl:e,sessionToken:t,uuid:n,fetchImpl:r}){let o=await r(b(e,n),{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});if(!o.ok)throw new Error(`GET /workflows/${n}/env \u2192 HTTP ${o.status}`);let s=await o.json();return Array.isArray(s?.keys)?s.keys:[]}function ue(e,t){if(!e?.length)return!1;try{let n=w(e);return t.some(r=>Object.prototype.hasOwnProperty.call(n,r)&&typeof n[r]=="string"&&n[r].trim().length>0)}catch{return!1}}async function le({workflowAgent:e,workflowUuid:t,authChoice:n,envFiles:r=[],sessionToken:o,apiUrl:s,fetchImpl:a=globalThis.fetch,readConfig:y=O}){if(!e)return{status:"error",detail:"workflowAgent unresolved (no agent in .zibby.config.mjs)"};let c=te[e];if(!c)return{status:"error",detail:`unknown agent: ${e}`};if(!o||!s)return{status:"error",detail:"missing sessionToken or apiUrl"};if(t)try{let d=await ce({apiUrl:s,sessionToken:o,uuid:t,fetchImpl:a}),A=c.find(f=>d.includes(f));if(A)return{status:"ok-already-set",acceptedVars:c,matchedVar:A}}catch(d){if(!/HTTP 404/.test(d.message))return{status:"error",detail:d.message}}if(ue(r,c))return{status:"ok-via-env-flag",acceptedVars:c};let u=ae(e,n,{readConfig:y});return u?{status:"mismatch-can-upload",acceptedVars:c,candidate:u}:{status:"mismatch-no-local",acceptedVars:c}}function Ce({uploadAs:e,value:t}){return $({[e]:t})}function $(e){let t=h(X(),`zibby-creds-${ee(8).toString("hex")}.env`),n=Object.entries(e).map(([o,s])=>{let a=String(s);return/[\s"'={}[\]:,]/.test(a)?`${o}='${a.replace(/'/g,"'\\''")}'`:`${o}=${a}`});W(t,`${n.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`,"utf-8");try{q(t,384)}catch{}let r=()=>{try{Q(t)}catch{}};return process.on("exit",r),process.on("SIGINT",()=>{r(),process.exit(130)}),t}function fe({workflowAgent:e,acceptedVars:t,projectId:n,log:r}){r(i.red(` \u2716 No local ${e} credentials found to upload.`)),r(i.red(` Cloud Fargate needs ${t.join(" or ")} in this workflow's env.`)),r(""),r(i.yellow(" Pick one:")),e==="claude"?(r(i.yellow(" A. Set up Claude OAuth (no API costs):")),r(i.gray(" 1. claude (the CLI from @anthropic-ai/claude-code) \u2192 log in, quit")),r(i.gray(" 2. zibby init -f # picks up the token")),r(i.gray(" 3. zibby workflow deploy <name> # we'll upload it")),r(i.yellow(" B. Buy a Claude API key (pay-per-token):")),r(i.gray(" https://console.anthropic.com/settings/keys")),r(i.gray(" zibby workflow env set <uuid> ANTHROPIC_API_KEY=sk-ant-..."))):(r(i.yellow(` A. Get an API key for ${e}:`)),r(i.gray(` zibby workflow env set <uuid> ${t[0]}=<your-key>`))),r(i.yellow(" C. Skip this gate (deploy WILL fail at trigger time):")),r(i.gray(" zibby workflow deploy <name> --no-creds-check")),r(i.gray(" (or set the project-level key at")),r(i.gray(` https://studio.zibby.dev/projects/${n}/settings)`)),r("")}async function Ne({userConfig:e,workflowDir:t,projectId:n,sessionToken:r,apiUrl:o,deployOptions:s,fetchImpl:a,readConfig:y,prompt:c,log:u=console.log,writeTempBag:d=$,readFullBlob:A=re}){let f=N(e);if(!f)return{proceed:!0};let x=oe(e),S=se(t),Y=Array.isArray(s?.env)?s.env:[],E=await le({workflowAgent:f,workflowUuid:S,authChoice:x,envFiles:Y,sessionToken:r,apiUrl:o,fetchImpl:a,readConfig:y});switch(E.status){case"ok-already-set":return{proceed:!0};case"ok-via-env-flag":return{proceed:!0};case"mismatch-can-upload":{let{candidate:l}=E,U=c||(async({message:p})=>{let{proceed:P}=await B.prompt([{type:"confirm",name:"proceed",message:p,default:!0}]);return P}),k=l.kind==="oauth"?"OAuth token":"API key",L=`Cloud workflow has no ${f} credentials. Upload your local ${k} (${l.uploadAs})?`,g;try{g=await U({message:L})}catch{g=!1}if(!g)return u(i.yellow(` \u26A0 Deploying without ${l.uploadAs} on the workflow.`)),u(i.yellow(" Trigger will fail until you set it manually:")),u(i.gray(` zibby workflow env set <uuid> ${l.uploadAs}=<your-token>`)),{proceed:!0};let _,v="";if(f==="claude"&&l.kind==="oauth"){let p=A();p&&p.accessToken?(_={CLAUDE_CODE_CREDENTIALS_JSON:JSON.stringify({claudeAiOauth:p}),CLAUDE_CODE_OAUTH_TOKEN:p.accessToken},v=" (full Keychain blob \u2014 accessToken + refreshToken + expiresAt + scopes)"):_={CLAUDE_CODE_OAUTH_TOKEN:l.value}}else _={[l.uploadAs]:l.value};let I=d(_);return s&&(Array.isArray(s.env)||(s.env=[]),s.env.push(I)),u(i.green(` \u2713 Will upload ${k}${v} to workflow env after deploy.`)),{proceed:!0,addedEnvFile:I}}case"mismatch-no-local":return fe({workflowAgent:f,acceptedVars:E.acceptedVars,projectId:n,log:u}),{proceed:!1};default:return u(i.gray(` (skipped cloud-creds sanity check: ${E.detail||"unknown error"})`)),{proceed:!0}}}export{ie as pickLocalUpload,se as readDeployedUuid,re as readFullClaudeOauthBlob,ae as readLocalUpload,oe as resolveAgentAuthChoice,le as resolveCheckResult,N as resolveWorkflowAgent,Ne as runCloudCredsCheck,$ as writeTempEnvBag,Ce as writeTempEnvFile};
|
|
@@ -1,58 +1,59 @@
|
|
|
1
|
-
var
|
|
1
|
+
var mo=Object.defineProperty;var O=(e,o)=>()=>(e&&(o=e(e=0)),o);var Ee=(e,o)=>{for(var t in o)mo(e,t,{get:o[t],enumerable:!0})};function C(){let e;if(process.env.ZIBBY_API_URL)e=process.env.ZIBBY_API_URL;else{let o=process.env.ZIBBY_ENV||"prod";F[o]?e=F[o].apiUrl:e=F.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)`),F.prod.apiUrl):e}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${e}`),F.prod.apiUrl}}var F,Z=O(()=>{F={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"}}});import{existsSync as Pe,mkdirSync as Eo,readFileSync as xo,writeFileSync as Io}from"fs";import{homedir as Ue}from"os";import{join as W}from"path";function Se(){return process.env.ZIBBY_CONFIG_DIR||W(Ue(),".zibby")}function Oe(){return W(Se(),"config.json")}function jo(){let e=Se();Pe(e)||Eo(e,{recursive:!0})}function B(){try{let e=Oe();if(Pe(e)){let o=xo(e,"utf-8");return JSON.parse(o)}}catch{}return{}}function G(e){jo(),Io(Oe(),JSON.stringify(e,null,2))}function Ce(){return B().sessionToken||null}function Ne(e){let o=B();o.sessionToken=e,G(o)}function Le(){return B().user||null}function Be(e){let o=B();o.user=e,G(o)}function Ke(e){let o=B();o.proxyUrl=e,G(o)}function ze(e){let o=B();o.mem0ProxyUrl=e,G(o)}function De(e){let o=B();o.projects=e,G(o)}var _o,_t,Re=O(()=>{_o=W(Ue(),".zibby"),_t=W(_o,"config.json")});import{existsSync as Pt,mkdirSync as Ut,readFileSync as St,writeFileSync as Ot,unlinkSync as Ct}from"fs";import{resolve as Lt}from"path";import{homedir as Kt}from"os";var Ye=O(()=>{});import h from"chalk";import le from"ora";import{spawn as To}from"child_process";function Po(e){let o=process.platform;try{let t,n;return o==="darwin"?(t="open",n=[e]):o==="win32"?(t="cmd",n=["/c","start","",e]):(t="xdg-open",n=[e]),To(t,n,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function Uo(){let e=Ce(),o=Le();return e&&o?{loggedIn:!0,user:o,token:e}:{loggedIn:!1}}async function Ge(){try{console.log(h.cyan(`
|
|
2
2
|
\u{1F510} Initiating login...
|
|
3
|
-
`));let e=
|
|
4
|
-
`));let{createInterface:o}=await import("readline"),t=o({input:process.stdin,output:process.stdout});return new Promise((n,r)=>{let i=()=>{t.close(),process.stdin.isTTY&&process.stdin.setRawMode(!1)},s=()=>{console.log(
|
|
3
|
+
`));let e=Uo();if(e.loggedIn){console.log(h.green("\u2705 Already logged in!")),console.log(h.gray(`User: ${e.user.email}`)),console.log(h.gray(`Name: ${e.user.name}
|
|
4
|
+
`));let{createInterface:o}=await import("readline"),t=o({input:process.stdin,output:process.stdout});return new Promise((n,r)=>{let i=()=>{t.close(),process.stdin.isTTY&&process.stdin.setRawMode(!1)},s=()=>{console.log(h.yellow(`
|
|
5
5
|
|
|
6
6
|
\u26A0\uFE0F Login cancelled
|
|
7
|
-
`)),i(),process.exit(0)};process.on("SIGINT",s),t.question(
|
|
8
|
-
`));let f=await
|
|
9
|
-
`)),n({success:!0,...e})}catch(f){r(f)}})})}return await
|
|
10
|
-
\u274C Login failed:`,e.message)),{success:!1,error:e.message}}}async function
|
|
7
|
+
`)),i(),process.exit(0)};process.on("SIGINT",s),t.question(h.yellow("Continue with this session? (Y/n): "),async c=>{process.removeListener("SIGINT",s),i();try{if(c.toLowerCase()==="n"||c.toLowerCase()==="no"){console.log(h.gray(`Starting new login...
|
|
8
|
+
`));let f=await Fe();n(f)}else console.log(h.green(`Using existing session.
|
|
9
|
+
`)),n({success:!0,...e})}catch(f){r(f)}})})}return await Fe()}catch(e){return console.error(h.red(`
|
|
10
|
+
\u274C Login failed:`,e.message)),{success:!1,error:e.message}}}async function So(e){let o=C();try{let t=await fetch(`${o}/projects`,{headers:{Authorization:`Bearer ${e}`}});if(t.ok){let r=((await t.json()).projects||[]).map(i=>({name:i.name,projectId:i.projectId,apiToken:i.apiToken}));return De(r),r}}catch(t){console.log(h.gray(`\u26A0\uFE0F Could not fetch projects: ${t.message}`))}return[]}async function Fe(){let e=C(),o=le("Requesting login code...").start(),t=await fetch(`${e}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!t.ok){o.fail("Failed to request login code");let u=await t.json();throw new Error(u.error||"Failed to initiate login")}let{deviceCode:n,userCode:r,verificationUrl:i,expiresIn:s,interval:c}=await t.json();o.succeed("Login code generated"),console.log(""),console.log(h.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(h.cyan("\u2551")+h.white.bold(" Complete login in your browser ")+h.cyan("\u2551")),console.log(h.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(h.white("Opening browser to login page...")),console.log(h.gray(`Code expires in ${Math.floor(s/60)} minutes`)),console.log(""),await Po(i)||(console.log(h.yellow("\u26A0\uFE0F Could not open browser automatically.")),console.log(h.white("Please open this URL manually: ")+h.blue(i)),console.log(""));let a=le("Waiting for authorization...").start(),g=(c||3)*1e3,x=Math.floor(s/(c||3)),d=0,_=!1,v=()=>{_=!0,a.stop(),console.log(h.yellow(`
|
|
11
11
|
|
|
12
12
|
\u26A0\uFE0F Login cancelled
|
|
13
|
-
`)),process.exit(0)};process.on("SIGINT",v);try{for(;
|
|
14
|
-
`)),{success:!0,loggedIn:!0,user:l.user,token:l.token}}if(l.status==="denied")throw a.fail("Authorization denied"),new Error("User denied authorization")}throw a.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",v)}}function
|
|
15
|
-
Not authenticated.`),console.log(` Run ${
|
|
16
|
-
`)}async function
|
|
17
|
-
Not logged in.`));let n;try{n=await
|
|
18
|
-
`)}var
|
|
19
|
-
|
|
13
|
+
`)),process.exit(0)};process.on("SIGINT",v);try{for(;d<x&&!_;){await Oo(g),d++;let u=await fetch(`${e}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:n})});if(u.status===202)continue;if(!u.ok){a.fail("Authorization failed");let y=await u.json();throw new Error(y.error||"Authorization failed")}let l=await u.json();if(l.status==="authorized"){a.succeed(h.white("Authorization successful!")),Ne(l.token),Be(l.user),l.proxyUrl&&Ke(l.proxyUrl),l.mem0ProxyUrl&&ze(l.mem0ProxyUrl),console.log(""),console.log(h.gray(`User: ${l.user.email}`));let y=le("Fetching projects...").start(),L=await So(l.token);return y.succeed(`Fetched ${L.length} project${L.length!==1?"s":""}`),console.log(h.gray(`Session saved to: ~/.zibby/config.json
|
|
14
|
+
`)),{success:!0,loggedIn:!0,user:l.user,token:l.token}}if(l.status==="denied")throw a.fail("Authorization denied"),new Error("User denied authorization")}throw a.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",v)}}function Oo(e){return new Promise(o=>setTimeout(o,e))}var Me=O(()=>{Z();Re();Ye()});import{existsSync as Co,readFileSync as No}from"fs";import{join as Lo}from"path";import fe from"chalk";import{confirm as Bo}from"@inquirer/prompts";function Ve(){try{let e=process.env.HOME||process.env.USERPROFILE;if(!e)return null;let o=Lo(e,".zibby","config.json");return Co(o)&&JSON.parse(No(o,"utf-8")).sessionToken||null}catch{return null}}function ue(){console.log(`
|
|
15
|
+
Not authenticated.`),console.log(` Run ${fe.cyan("zibby login")} or set ${fe.cyan("ZIBBY_API_KEY")} in your environment.
|
|
16
|
+
`)}async function q(e={}){let o=e.apiKey||process.env.ZIBBY_API_KEY||null,t=Ve();if(t||o)return{sessionToken:t,apiKey:o};if(!process.stdin.isTTY){if(e.optional)return{sessionToken:null,apiKey:null};ue(),process.exit(1)}console.log(fe.yellow(`
|
|
17
|
+
Not logged in.`));let n;try{n=await Bo({message:"Open browser to log in now?",default:!0})}catch{n=!1}if(!n){if(e.optional)return{sessionToken:null,apiKey:null};ue(),process.exit(1)}if(await Ge(),t=Ve(),!t){if(e.optional)return{sessionToken:null,apiKey:null};ue(),process.exit(1)}return{sessionToken:t,apiKey:null}}var pe=O(()=>{Me()});import{existsSync as Ko,readFileSync as zo,writeFileSync as tn,mkdirSync as nn}from"fs";import{join as Do}from"path";import{homedir as Ro}from"os";function Yo(){return Do(Ro(),".zibby","config.json")}function de(){try{let e=Yo();return Ko(e)?JSON.parse(zo(e,"utf-8")):{}}catch{return{}}}var Q,He=O(()=>{Q={cursor:{envVar:"CURSOR_API_KEY",label:"Cursor API Key",url:"https://cursor.com/settings"},claude:{envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com/settings/keys"},codex:{envVar:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com/api-keys"},gemini:{envVar:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com/app/apikey"}}});import{readFileSync as Fo,existsSync as Go}from"fs";import Mo from"dotenv";function X(e){return typeof e=="string"&&ge.test(e)}function Je(e){if(typeof e!="string"||e.length===0)throw new Error("Expected KEY=value, got empty argument");let o=e.indexOf("=");if(o<=0)throw new Error(`Expected KEY=value, got "${e}" \u2014 missing '=' or empty key`);let t=e.slice(0,o),n=e.slice(o+1);if(!X(t))throw new Error(`Invalid env var name "${t}" \u2014 must match ${ge} (uppercase letters, digits, underscores; can't start with a digit)`);return{key:t,value:n}}function M(e){if(!Array.isArray(e)||e.length===0)return{};let o={};for(let t of e){if(!Go(t))throw new Error(`--env file not found: ${t}`);let n=Mo.parse(Fo(t,"utf-8"));for(let[r,i]of Object.entries(n)){if(!X(r))throw new Error(`Invalid env var name "${r}" in ${t} \u2014 must match ${ge} (uppercase letters, digits, underscores; can't start with a digit)`);o[r]=i}}return o}function N(e,o,t){let n=String(e).replace(/\/+$/,"");return t?`${n}/workflows/${o}/env/${encodeURIComponent(t)}`:`${n}/workflows/${o}/env`}function ye(e){return!Array.isArray(e)||e.length===0?"No env vars set on this workflow.":[...e].sort().map(t=>` ${t}`).join(`
|
|
18
|
+
`)}var ge,he=O(()=>{ge=/^[A-Z_][A-Z0-9_]*$/});var no={};Ee(no,{pickLocalUpload:()=>eo,readDeployedUuid:()=>Xe,readFullClaudeOauthBlob:()=>qe,readLocalUpload:()=>oo,resolveAgentAuthChoice:()=>Qe,resolveCheckResult:()=>to,resolveWorkflowAgent:()=>we,runCloudCredsCheck:()=>it,writeTempEnvBag:()=>ke,writeTempEnvFile:()=>rt});import m from"chalk";import Vo from"inquirer";import{execSync as Ho}from"node:child_process";import{existsSync as Ze,readFileSync as We,writeFileSync as Jo,chmodSync as Zo,unlinkSync as Wo}from"node:fs";import{homedir as qo,tmpdir as Qo}from"node:os";import{join as me}from"node:path";import{randomBytes as Xo}from"node:crypto";function qe(){if(process.platform==="darwin")try{let e=Ho('security find-generic-password -s "Claude Code-credentials" -w',{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim();if(e){let o=JSON.parse(e);if(o?.claudeAiOauth?.accessToken)return o.claudeAiOauth}}catch{}try{let e=me(qo(),".claude",".credentials.json");return Ze(e)&&JSON.parse(We(e,"utf-8"))?.claudeAiOauth||null}catch{return null}}function Qe(e){let o=we(e);if(!o)return null;let t=e?.agent;if(!t||typeof t!="object")return null;let n=t[o];if(n&&typeof n=="object"&&typeof n.auth=="string"){let r=n.auth.toLowerCase();if(r==="oauth"||r==="api")return r}return null}function we(e){if(!e||typeof e!="object")return null;let o=e.agent;if(!o)return null;if(typeof o=="string")return Q[o]?o:null;if(typeof o=="object"){if(typeof o.provider=="string"&&Q[o.provider])return o.provider;for(let t of Object.keys(o))if(Q[t])return t}return null}function Xe(e){if(!e)return null;let o=me(e,".zibby-deploy.json");if(!Ze(o))return null;try{let t=JSON.parse(We(o,"utf-8"));if(typeof t?.uuid=="string"&&t.uuid)return t.uuid}catch{}return null}function eo(e,o,t){let r=(ot[e]||[]).slice().sort((i,s)=>t&&i.kind===t&&s.kind!==t?-1:t&&s.kind===t&&i.kind!==t?1:0);for(let i of r){let s=o?.[i.localVar];if(typeof s=="string"&&s.trim())return{...i,value:s.trim()}}return null}function oo(e,o,{readConfig:t=de}={}){let n=t()||{},r=n.agentKeys&&typeof n.agentKeys=="object"?n.agentKeys:{};return eo(e,r,o)}async function tt({apiUrl:e,sessionToken:o,uuid:t,fetchImpl:n}){let r=await n(N(e,t),{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});if(!r.ok)throw new Error(`GET /workflows/${t}/env \u2192 HTTP ${r.status}`);let i=await r.json();return Array.isArray(i?.keys)?i.keys:[]}function nt(e,o){if(!e?.length)return!1;try{let t=M(e);return o.some(n=>Object.prototype.hasOwnProperty.call(t,n)&&typeof t[n]=="string"&&t[n].trim().length>0)}catch{return!1}}async function to({workflowAgent:e,workflowUuid:o,authChoice:t,envFiles:n=[],sessionToken:r,apiUrl:i,fetchImpl:s=globalThis.fetch,readConfig:c=de}){if(!e)return{status:"error",detail:"workflowAgent unresolved (no agent in .zibby.config.mjs)"};let f=et[e];if(!f)return{status:"error",detail:`unknown agent: ${e}`};if(!r||!i)return{status:"error",detail:"missing sessionToken or apiUrl"};if(o)try{let g=await tt({apiUrl:i,sessionToken:r,uuid:o,fetchImpl:s}),x=f.find(d=>g.includes(d));if(x)return{status:"ok-already-set",acceptedVars:f,matchedVar:x}}catch(g){if(!/HTTP 404/.test(g.message))return{status:"error",detail:g.message}}if(nt(n,f))return{status:"ok-via-env-flag",acceptedVars:f};let a=oo(e,t,{readConfig:c});return a?{status:"mismatch-can-upload",acceptedVars:f,candidate:a}:{status:"mismatch-no-local",acceptedVars:f}}function rt({uploadAs:e,value:o}){return ke({[e]:o})}function ke(e){let o=me(Qo(),`zibby-creds-${Xo(8).toString("hex")}.env`),t=Object.entries(e).map(([r,i])=>{let s=String(i);return/[\s"'={}[\]:,]/.test(s)?`${r}='${s.replace(/'/g,"'\\''")}'`:`${r}=${s}`});Jo(o,`${t.join(`
|
|
19
|
+
`)}
|
|
20
|
+
`,"utf-8");try{Zo(o,384)}catch{}let n=()=>{try{Wo(o)}catch{}};return process.on("exit",n),process.on("SIGINT",()=>{n(),process.exit(130)}),o}function st({workflowAgent:e,acceptedVars:o,projectId:t,log:n}){n(m.red(` \u2716 No local ${e} credentials found to upload.`)),n(m.red(` Cloud Fargate needs ${o.join(" or ")} in this workflow's env.`)),n(""),n(m.yellow(" Pick one:")),e==="claude"?(n(m.yellow(" A. Set up Claude OAuth (no API costs):")),n(m.gray(" 1. claude (the CLI from @anthropic-ai/claude-code) \u2192 log in, quit")),n(m.gray(" 2. zibby init -f # picks up the token")),n(m.gray(" 3. zibby workflow deploy <name> # we'll upload it")),n(m.yellow(" B. Buy a Claude API key (pay-per-token):")),n(m.gray(" https://console.anthropic.com/settings/keys")),n(m.gray(" zibby workflow env set <uuid> ANTHROPIC_API_KEY=sk-ant-..."))):(n(m.yellow(` A. Get an API key for ${e}:`)),n(m.gray(` zibby workflow env set <uuid> ${o[0]}=<your-key>`))),n(m.yellow(" C. Skip this gate (deploy WILL fail at trigger time):")),n(m.gray(" zibby workflow deploy <name> --no-creds-check")),n(m.gray(" (or set the project-level key at")),n(m.gray(` https://studio.zibby.dev/projects/${t}/settings)`)),n("")}async function it({userConfig:e,workflowDir:o,projectId:t,sessionToken:n,apiUrl:r,deployOptions:i,fetchImpl:s,readConfig:c,prompt:f,log:a=console.log,writeTempBag:g=ke,readFullBlob:x=qe}){let d=we(e);if(!d)return{proceed:!0};let _=Qe(e),v=Xe(o),u=Array.isArray(i?.env)?i.env:[],l=await to({workflowAgent:d,workflowUuid:v,authChoice:_,envFiles:u,sessionToken:n,apiUrl:r,fetchImpl:s,readConfig:c});switch(l.status){case"ok-already-set":return{proceed:!0};case"ok-via-env-flag":return{proceed:!0};case"mismatch-can-upload":{let{candidate:y}=l,L=f||(async({message:U})=>{let{proceed:R}=await Vo.prompt([{type:"confirm",name:"proceed",message:U,default:!0}]);return R}),T=y.kind==="oauth"?"OAuth token":"API key",P=`Cloud workflow has no ${d} credentials. Upload your local ${T} (${y.uploadAs})?`,E;try{E=await L({message:P})}catch{E=!1}if(!E)return a(m.yellow(` \u26A0 Deploying without ${y.uploadAs} on the workflow.`)),a(m.yellow(" Trigger will fail until you set it manually:")),a(m.gray(` zibby workflow env set <uuid> ${y.uploadAs}=<your-token>`)),{proceed:!0};let b,D="";if(d==="claude"&&y.kind==="oauth"){let U=x();U&&U.accessToken?(b={CLAUDE_CODE_CREDENTIALS_JSON:JSON.stringify({claudeAiOauth:U}),CLAUDE_CODE_OAUTH_TOKEN:U.accessToken},D=" (full Keychain blob \u2014 accessToken + refreshToken + expiresAt + scopes)"):b={CLAUDE_CODE_OAUTH_TOKEN:y.value}}else b={[y.uploadAs]:y.value};let K=g(b);return i&&(Array.isArray(i.env)||(i.env=[]),i.env.push(K)),a(m.green(` \u2713 Will upload ${T}${D} to workflow env after deploy.`)),{proceed:!0,addedEnvFile:K}}case"mismatch-no-local":return st({workflowAgent:d,acceptedVars:l.acceptedVars,projectId:t,log:a}),{proceed:!1};default:return a(m.gray(` (skipped cloud-creds sanity check: ${l.detail||"unknown error"})`)),{proceed:!0}}}var et,ot,ro=O(()=>{He();he();et={claude:["ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN"],cursor:["CURSOR_API_KEY"],codex:["OPENAI_API_KEY"],gemini:["GOOGLE_API_KEY"]};ot={claude:[{localVar:"ANTHROPIC_API_KEY",uploadAs:"ANTHROPIC_API_KEY",kind:"api"},{localVar:"CLAUDE_CODE_OAUTH_TOKEN",uploadAs:"CLAUDE_CODE_OAUTH_TOKEN",kind:"oauth"}],cursor:[{localVar:"CURSOR_API_KEY",uploadAs:"CURSOR_API_KEY",kind:"api"}],codex:[{localVar:"OPENAI_API_KEY",uploadAs:"OPENAI_API_KEY",kind:"api"}],gemini:[{localVar:"GEMINI_API_KEY",uploadAs:"GOOGLE_API_KEY",kind:"api"},{localVar:"GOOGLE_API_KEY",uploadAs:"GOOGLE_API_KEY",kind:"api"}]}});var so={};Ee(so,{listEnvCommand:()=>ct,pushEnvCommand:()=>ut,setEnvCommand:()=>at,syncEnvFromFiles:()=>ft,unsetEnvCommand:()=>lt});import k from"chalk";import ee from"ora";async function oe(e){let{sessionToken:o,apiKey:t}=await q({apiKey:e.apiKey}),n=o||t;return n||(console.log(k.red("\n Not authenticated \u2014 run `zibby login` or pass --api-key.\n")),process.exit(1)),{authToken:n,apiUrl:C()}}async function te(e,o,t,n,r){let i={method:e,headers:{Authorization:`Bearer ${t}`,...n?{"Content-Type":"application/json"}:{}},...n?{body:JSON.stringify(n)}:{}},s;try{s=await fetch(o,i)}catch(f){r&&r.fail(`Network error: ${f.message}`),process.exit(1)}let c;try{c=await s.json()}catch{c={}}return s.ok||(r?r.fail(c.error||c.message||`HTTP ${s.status}`):console.log(k.red(`
|
|
20
21
|
${c.error||c.message||`HTTP ${s.status}`}
|
|
21
|
-
`)),process.exit(1)),c}async function
|
|
22
|
-
Workflow UUID is required`)),console.log(
|
|
23
|
-
`)),process.exit(1));let{authToken:t,apiUrl:n}=await
|
|
24
|
-
Last updated: ${i.envUpdatedAt}`)),console.log("")}async function
|
|
25
|
-
Both UUID and KEY=value are required`)),console.log(
|
|
26
|
-
`)),process.exit(1));let n,r;try{({key:n,value:r}=
|
|
27
|
-
${
|
|
28
|
-
`)),process.exit(1)}let{authToken:i,apiUrl:s}=await
|
|
29
|
-
Both UUID and KEY are required`)),console.log(
|
|
30
|
-
`)),process.exit(1)),
|
|
22
|
+
`)),process.exit(1)),c}async function ct(e,o={}){e||(console.log(k.red(`
|
|
23
|
+
Workflow UUID is required`)),console.log(k.gray(` Usage: zibby workflow env list <uuid>
|
|
24
|
+
`)),process.exit(1));let{authToken:t,apiUrl:n}=await oe(o),r=ee(`Fetching env keys for ${e}...`).start(),i=await te("GET",N(n,e),t,null,r),s=i.keys||[];r.succeed(`${s.length} env var${s.length===1?"":"s"} on workflow ${e}`),console.log(""),console.log(ye(s)),i.envUpdatedAt&&console.log(k.gray(`
|
|
25
|
+
Last updated: ${i.envUpdatedAt}`)),console.log("")}async function at(e,o,t={}){(!e||!o)&&(console.log(k.red(`
|
|
26
|
+
Both UUID and KEY=value are required`)),console.log(k.gray(` Usage: zibby workflow env set <uuid> KEY=value
|
|
27
|
+
`)),process.exit(1));let n,r;try{({key:n,value:r}=Je(o))}catch(g){console.log(k.red(`
|
|
28
|
+
${g.message}
|
|
29
|
+
`)),process.exit(1)}let{authToken:i,apiUrl:s}=await oe(t),c=ee(`Setting ${n} on workflow ${e}...`).start(),a=((await te("PATCH",N(s,e,n),i,{value:r},c)).keys||[]).length;c.succeed(`Set ${k.cyan(n)} (workflow now has ${a} env var${a===1?"":"s"})`)}async function lt(e,o,t={}){(!e||!o)&&(console.log(k.red(`
|
|
30
|
+
Both UUID and KEY are required`)),console.log(k.gray(` Usage: zibby workflow env unset <uuid> KEY
|
|
31
|
+
`)),process.exit(1)),X(o)||(console.log(k.red(`
|
|
31
32
|
Invalid env var name "${o}"
|
|
32
|
-
`)),process.exit(1));let{authToken:n,apiUrl:r}=await
|
|
33
|
-
Workflow UUID is required`)),console.log(
|
|
34
|
-
`)),process.exit(1));let t=Array.isArray(o.file)?o.file:o.file?[o.file]:[];t.length===0&&(console.log(
|
|
35
|
-
At least one --file is required`)),console.log(
|
|
36
|
-
`)),process.exit(1));let n;try{n=
|
|
33
|
+
`)),process.exit(1));let{authToken:n,apiUrl:r}=await oe(t),i=ee(`Unsetting ${o} on workflow ${e}...`).start(),s=await te("DELETE",N(r,e,o),n,null,i),c=(s.keys||[]).length;s.removed?i.succeed(`Unset ${k.cyan(o)} (workflow now has ${c} env var${c===1?"":"s"})`):i.warn(`Key ${k.cyan(o)} was not set on workflow ${e} \u2014 nothing to do`)}async function ut(e,o={}){e||(console.log(k.red(`
|
|
34
|
+
Workflow UUID is required`)),console.log(k.gray(` Usage: zibby workflow env push <uuid> --file .env [--file .env.prod]
|
|
35
|
+
`)),process.exit(1));let t=Array.isArray(o.file)?o.file:o.file?[o.file]:[];t.length===0&&(console.log(k.red(`
|
|
36
|
+
At least one --file is required`)),console.log(k.gray(` Usage: zibby workflow env push <uuid> --file .env
|
|
37
|
+
`)),process.exit(1));let n;try{n=M(t)}catch(f){console.log(k.red(`
|
|
37
38
|
${f.message}
|
|
38
|
-
`)),process.exit(1)}let r=Object.keys(n);r.length===0&&(console.log(
|
|
39
|
+
`)),process.exit(1)}let r=Object.keys(n);r.length===0&&(console.log(k.yellow(`
|
|
39
40
|
No env vars found in ${t.join(", ")} \u2014 nothing to push.
|
|
40
|
-
`)),process.exit(0));let{authToken:i,apiUrl:s}=await
|
|
41
|
-
`);continue}
|
|
42
|
-
`)}if(i.text=
|
|
41
|
+
`)),process.exit(0));let{authToken:i,apiUrl:s}=await oe(o),c=ee(`Pushing ${r.length} env var${r.length===1?"":"s"} to ${e}...`).start();await te("PUT",N(s,e),i,{env:n},c),c.succeed(`Pushed ${r.length} env var${r.length===1?"":"s"} from ${t.join(", ")}`),console.log(""),console.log(ye(r)),console.log("")}async function ft({uuid:e,files:o,authToken:t,apiUrl:n,spinner:r}){let i=M(o),s=Object.keys(i);if(s.length===0)return{count:0,files:o};let c=N(n,e),f={method:"PUT",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({env:i})},a=await fetch(c,f);if(!a.ok){let g=await a.json().catch(()=>({}));throw new Error(`Env push failed: ${g.error||g.message||`HTTP ${a.status}`}`)}return r&&(r.text=`Synced ${s.length} env var${s.length===1?"":"s"} to workflow`),{count:s.length,files:o}}var io=O(()=>{pe();Z();he()});import{existsSync as j,readFileSync as ve,writeFileSync as pt}from"fs";import{join as A}from"path";import $ from"chalk";import ne from"ora";import dt from"dotenv";import{select as co}from"@inquirer/prompts";import{existsSync as wo}from"fs";import{join as ko}from"path";import{pathToFileURL as vo}from"url";async function xe(e){let o=ko(e,".zibby.config.mjs");if(!wo(o))throw new Error(".zibby.config.mjs not found");try{let t=await import(vo(o).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}Z();function Ie(e,o){return e?.uuid||e?.workflowUuid||o?.uuid||null}var bo=4;function ae({elapsedMs:e,phase:o,step:t}){let r=` \u2014 ${Math.max(0,Math.floor(e/1e3))}s`;return t?`Building bundle on Zibby Cloud... [${t.n}/${bo}] ${t.label}${r}`:o?`Building bundle on Zibby Cloud... (${o.toLowerCase()})${r}`:`Building bundle on Zibby Cloud...${r}`}var Ao=/\[(\d+)\/\d+\]\s+(.+?)\s*\.{0,3}\s*$/;function _e(e){if(!e)return null;let o=Ao.exec(e);if(!o)return null;let t=parseInt(o[1],10);return!Number.isInteger(t)||t<1?null:{n:t,label:o[2].trim()}}function je(){let e=!1;return function(t){if(!t)return!0;let n=t.replace(/\s+$/,"");if(e)return/^\s*"\s*$/.test(n)&&(e=!1),!0;if(!$o(t))return!1;let r=n.replace(/^\[Container\]\s+\d{4}\/\d{2}\/\d{2}\s+\d{2}:\d{2}:\d{2}\.\d+\s*/,"");return r.startsWith("Running command ")&&(r.match(/"/g)||[]).length%2===1&&(e=!0),!0}}function $o(e){if(!e)return!0;let t=e.trim().replace(/^\[Container\]\s+\d{4}\/\d{2}\/\d{2}\s+\d{2}:\d{2}:\d{2}\.\d+\s*/,"");return!!(/^Phase complete:/.test(t)||/^Phase context status code:/.test(t)||/^Entering phase /.test(t)||/^Running command /.test(t)||/^Phase is /.test(t)||/^Waiting for /.test(t)||/^Registering with agent$/.test(t)||/^Running on CodeBuild /.test(t)||/^Phases found in YAML:/.test(t)||/^CODEBUILD_SRC_DIR=/.test(t)||/^YAML location is /.test(t)||/^Processing environment variables$/.test(t)||/^Moving to directory /.test(t)||/^Cache is not defined /.test(t)||/^Skip cache due to:/.test(t)||/^\s*INSTALL: \d+ commands?$/.test(t)||/^\s*BUILD: \d+ commands?$/.test(t)||/^Set report auto-discover timeout/.test(t)||/^Expanding /.test(t)||/^Assembling file list$/.test(t)||/^No matching auto-discover/.test(t)||/^Report auto-discover/.test(t)||t==="")}function Te({uuid:e,name:o,projectId:t,result:n,existingManifest:r=null,now:i=()=>new Date().toISOString()}){let s=n?.version??(r?.version??0)+1;return{uuid:e,name:o,projectId:t,version:s,deployedAt:i()}}pe();dt.config();async function gt({apiUrl:e,projectId:o,workflowName:t,buildId:n,authToken:r,spinner:i,verbose:s}){let c=Date.now(),f,a=null,g=null,x=je(),d=setInterval(()=>{i.text=ae({elapsedMs:Date.now()-c,phase:a,step:g})},1e3);try{for(;;){let _=new URL(`${e}/projects/${o}/workflows/${t}/build/${n}`);f&&_.searchParams.set("logsToken",f);let v;try{let u=await fetch(_,{headers:{Authorization:`Bearer ${r}`}});if(!u.ok)throw new Error(`HTTP ${u.status}`);v=await u.json()}catch{await new Promise(l=>setTimeout(l,2e3));continue}v.phase&&v.phase!==a&&(a=v.phase),v.nextLogsToken&&v.nextLogsToken!==f&&(f=v.nextLogsToken);for(let u of v.logEvents||[]){let l=String(u.m||"").trimEnd();if(!l)continue;let y=_e(l);if(y&&(g=y),s){process.stdout.write(` ${l}
|
|
42
|
+
`);continue}x(l)||y||process.stdout.write(` ${l}
|
|
43
|
+
`)}if(i.text=ae({elapsedMs:Date.now()-c,phase:a,step:g}),v.done){let u=(Date.now()-c)/1e3;return{status:v.status,elapsedSec:u,lastPhase:a}}await new Promise(u=>setTimeout(u,2e3))}}finally{clearInterval(d)}}async function yt(e,o){let t=C(),n=ne("Fetching projects...").start();try{let r=o||e,i=await fetch(`${t}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});i.ok||(n.fail("Failed to fetch projects"),process.exit(1));let s=await i.json();Array.isArray(s)||(s.projects&&Array.isArray(s.projects)?s=s.projects:s.data&&Array.isArray(s.data)?s=s.data:(n.fail("Unexpected response format"),process.exit(1))),(!s||s.length===0)&&(n.fail("No projects found"),process.exit(1)),n.succeed(`Found ${s.length} project${s.length===1?"":"s"}`),console.log("");let c=s.map(a=>{let g=a.projectId||a.id||a._id||"unknown";return{name:`${a.name||a.projectName||"Unnamed"} (${g})`,value:g}});return await co({message:"Select a project to deploy to:",choices:c})}catch(r){n.fail(`Error: ${r.message}`),process.exit(1)}}async function Nn(e,o={}){let t=process.cwd(),n=".zibby/workflows",r=null;try{r=await xe(t),n=r?.paths?.workflows||".zibby/workflows"}catch{}if(e){let u=A(t,n,e);j(u)||(console.log(`
|
|
43
44
|
Error: Workflow not found: ${n}/${e}/`),console.log(" Run `zibby workflow list` to see local workflows,"),console.log(` or scaffold a new one: zibby workflow new ${e}
|
|
44
45
|
`),process.exit(1))}else{let u=A(t,n);j(u)||(console.log(`
|
|
45
46
|
Error: No workflows found in ${n}/`),console.log(` Create one with: zibby workflow new <name>
|
|
46
|
-
`),process.exit(1));let{readdir:l,stat:
|
|
47
|
+
`),process.exit(1));let{readdir:l,stat:y}=await import("fs/promises"),L=await l(u),T=[];for(let P of L){let E=A(u,P);if(!(await y(E)).isDirectory())continue;(j(A(E,"graph.mjs"))||j(A(E,"graph.js")))&&T.push(P)}T.length===0&&(console.log(`
|
|
47
48
|
Error: No workflows found in ${n}/`),console.log(` Create one with: zibby workflow new <name>
|
|
48
|
-
`),process.exit(1)),console.log(""),e=await
|
|
49
|
-
Error: graph.mjs not found in ${n}/${e}/`),process.exit(1)),o.credsCheck!==!1)try{let{runCloudCredsCheck:u}=await Promise.resolve().then(()=>(
|
|
49
|
+
`),process.exit(1)),console.log(""),e=await co({message:"Select a workflow to deploy:",choices:T.map(P=>({name:P,value:P}))})}let{sessionToken:i,apiKey:s}=await q({apiKey:o.apiKey}),c=o.project||process.env.ZIBBY_PROJECT_ID;c||(console.log(""),c=await yt(s,i));let f=i||s,a=A(t,n,e),g=A(a,"graph.mjs"),x=A(a,"workflow.json");if(j(g)||(console.log(`
|
|
50
|
+
Error: graph.mjs not found in ${n}/${e}/`),process.exit(1)),o.credsCheck!==!1)try{let{runCloudCredsCheck:u}=await Promise.resolve().then(()=>(ro(),no));(await u({userConfig:r,workflowDir:a,projectId:c,sessionToken:f,apiUrl:C(),deployOptions:o})).proceed||(console.log(""),process.exit(1))}catch(u){console.log($.gray(` (creds-check skipped: ${u.message})`))}console.log(`
|
|
50
51
|
Deploying Workflow
|
|
51
|
-
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${e}`),console.log(` Project: ${c}`),console.log(" ".padEnd(60,"-")),console.log("");let
|
|
52
|
-
`),process.exit(1)}let
|
|
53
|
-
`),process.exit(1)}
|
|
54
|
-
`),process.exit(1)}let
|
|
55
|
-
`,"utf-8")}catch(
|
|
56
|
-
`)}}catch(
|
|
57
|
-
`))}}console.log(""),
|
|
58
|
-
`),process.exit(1)}}export{
|
|
52
|
+
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${e}`),console.log(` Project: ${c}`),console.log(" ".padEnd(60,"-")),console.log("");let d=ne("Validating workflow...").start(),_=ve(g,"utf-8");if(_.includes("@zibby/core")||_.includes("@zibby/skills")){let u=A(a,"package.json");j(u)||(d.fail("Missing package.json"),console.log(""),console.log($.red(" \u2717 graph.mjs imports @zibby packages but no package.json found")),console.log(""),console.log($.yellow(" Create package.json with:")),console.log(""),console.log($.gray(" {")),console.log($.gray(' "type": "module",')),console.log($.gray(' "dependencies": {')),console.log($.gray(' "@zibby/core": "workspace:*"')),console.log($.gray(" }")),console.log($.gray(" }")),console.log(""),process.exit(1));let l=JSON.parse(ve(u,"utf-8"));!{...l.dependencies,...l.devDependencies}["@zibby/core"]&&_.includes("@zibby/core")&&(d.fail("Missing @zibby/core dependency"),console.log(""),console.log($.red(" \u2717 graph.mjs imports @zibby/core but it's not in package.json")),console.log(""),console.log($.yellow(" Add to package.json dependencies:")),console.log($.gray(' "@zibby/core": "workspace:*"')),console.log(""),process.exit(1))}d.text="Loading workflow graph...";try{let{pathToFileURL:u}=await import("url"),l=await import(u(g).href),y;if(l.default)if(typeof l.default=="function"){let p=l.default.prototype;p&&p.buildGraph?y=new l.default:y=l.default()}else d.fail("graph.mjs must export a class or factory function"),process.exit(1);else{let p=Object.values(l).find(w=>w.prototype&&w.prototype.buildGraph);p?y=new p:(d.fail("graph.mjs must export a WorkflowAgent class or factory function"),process.exit(1))}let T=y.buildGraph().serialize(),{readdir:P,readFile:E}=await import("fs/promises"),b={};d.text="Packaging workflow sources...";let D=await E(g,"utf-8");if(b["graph.mjs"]=D,j(x)){let p=await E(x,"utf-8");b["workflow.json"]=p}let K=A(a,"nodes");if(j(K)){let p=await P(K);for(let w of p)if(w.endsWith(".mjs")||w.endsWith(".js")){let I=A(K,w),ce=await E(I,"utf-8");b[`nodes/${w}`]=ce}}let U=A(a,"package.json");if(j(U)){let p=await E(U,"utf-8");b["package.json"]=p,d.text="Including package.json for dependencies..."}let R=A(a,"package-lock.json");if(j(R)){let p=await E(R,"utf-8");b["package-lock.json"]=p}r&&typeof r=="object"&&(b["zibby.config.json"]=JSON.stringify(r,null,2)),d.text=`Uploading to cloud (${T.nodes.size||Object.keys(T.nodes||{}).length} nodes, ${Object.keys(b).length} files)...`;let Y=C(),be=JSON.stringify({format:1,sources:b}),Ae=Buffer.byteLength(be,"utf8"),V=await fetch(`${Y}/projects/${c}/workflows/${e}/sources/presign`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`},body:JSON.stringify({contentLength:Ae})});if(!V.ok){let p=await V.json().catch(()=>({}));d.fail("Deploy failed (presign)"),console.log(` Error: ${p.error||p.message||V.statusText}
|
|
53
|
+
`),process.exit(1)}let ao=await V.json(),{uploadUrl:lo,key:uo,headers:fo}=ao,re=await fetch(lo,{method:"PUT",headers:{...fo||{},"Content-Length":String(Ae)},body:be});if(!re.ok){let p=await re.text().catch(()=>"");d.fail("Deploy failed (S3 upload)"),console.log(` S3 PUT failed: ${re.status} ${p.slice(0,200)}
|
|
54
|
+
`),process.exit(1)}d.text="Saving workflow definition...";let H=await fetch(`${Y}/projects/${c}/workflows/${e}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`},body:JSON.stringify({graph:T,sourcesStagingKey:uo,isDefault:!1})});if(!H.ok){let p=await H.json().catch(()=>({}));d.fail("Deploy failed"),console.log(` Error: ${p.message||p.error||H.statusText}
|
|
55
|
+
`),process.exit(1)}let se=await H.json(),J=A(a,".zibby-deploy.json"),ie=j(J)?(()=>{try{return JSON.parse(ve(J,"utf-8"))}catch{return null}})():null,S=Ie(se,ie);if(S){let p=Te({uuid:S,name:e,projectId:c,result:se,existingManifest:ie});try{pt(J,`${JSON.stringify(p,null,2)}
|
|
56
|
+
`,"utf-8")}catch(w){console.log(` Warning: failed to write ${J}: ${w.message}`)}}let po=ie?"Updated":"Deployed";if(d.succeed(`${po} ${e} (v${se.version||1})`),!(o.noWait===!0||process.env.ZIBBY_DEPLOY_NO_BUNDLE==="1")){console.log("");let p=ne("Building bundle on Zibby Cloud...").start();try{let w=await fetch(`${Y}/projects/${c}/workflows/${e}/build`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`}});if(w.ok){let I=await w.json(),{buildId:ce}=I,go=o.verbose===!0||process.env.ZIBBY_DEPLOY_VERBOSE==="1",{status:$e,elapsedSec:yo,lastPhase:ho}=await gt({apiUrl:Y,projectId:c,workflowName:e,buildId:ce,authToken:f,spinner:p,verbose:go});$e==="SUCCEEDED"?p.succeed(`Bundle ready (${yo.toFixed(1)}s) \u2014 runtime npm install eliminated`):p.warn(`Bundle build ${$e} at phase ${ho||"unknown"} \u2014 workflow will fall back to runtime install`)}else{let I=await w.json().catch(()=>({}));p.warn(`Bundle build skipped: ${I.error||I.message||w.statusText}`),console.log(` Workflow will use slower runtime install path until next deploy.
|
|
57
|
+
`)}}catch(w){p.warn(`Bundle build error: ${w.message}`)}}let z=Array.isArray(o.env)?o.env:o.env?[o.env]:[];if(z.length>0)if(!S)console.log($.yellow(" Skipping --env sync: deploy did not return a workflow UUID."));else{console.log("");let p=ne(`Syncing env from ${z.join(", ")}...`).start();try{let{syncEnvFromFiles:w}=await Promise.resolve().then(()=>(io(),so)),{count:I}=await w({uuid:S,files:z,authToken:f,apiUrl:Y,spinner:p});I===0?p.warn(`No env vars found in ${z.join(", ")} \u2014 workflow env unchanged.`):p.succeed(`Synced ${I} env var${I===1?"":"s"} from ${z.join(", ")}`)}catch(w){p.fail(`Env sync failed: ${w.message}`),console.log($.gray(` Re-run after fixing: zibby workflow env push ${S} ${z.map(I=>`--file ${I}`).join(" ")}
|
|
58
|
+
`))}}console.log(""),S&&console.log(` UUID: ${S}`),console.log(""),console.log(" Next steps:"),console.log(` zibby workflow run ${e} Run locally`),S&&console.log(` zibby workflow trigger ${S} Run in cloud`),console.log(" zibby workflow list View all workflows"),console.log("")}catch(u){d.fail("Deploy failed"),console.log(` Error: ${u.message}
|
|
59
|
+
`),process.exit(1)}}export{Nn as deployWorkflowCommand};
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
36
|
"@zibby/agent-workflow": "^0.3.2",
|
|
37
|
-
"@zibby/core": "^0.3.
|
|
37
|
+
"@zibby/core": "^0.3.4",
|
|
38
38
|
"@zibby/ui-memory": "^1.0.0",
|
|
39
39
|
"@zibby/skills": "^0.1.11",
|
|
40
40
|
"adm-zip": "^0.5.17",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
36
|
"@zibby/agent-workflow": "^0.3.2",
|
|
37
|
-
"@zibby/core": "^0.3.
|
|
37
|
+
"@zibby/core": "^0.3.4",
|
|
38
38
|
"@zibby/ui-memory": "^1.0.0",
|
|
39
39
|
"@zibby/skills": "^0.1.11",
|
|
40
40
|
"adm-zip": "^0.5.17",
|