@zibby/cli 0.1.58 → 0.1.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,18 @@
1
- import e from"chalk";import y from"ora";import{spawn as U}from"child_process";import{getApiUrl as p}from"../config/environments.js";import{saveSessionToken as $,saveUserInfo as x,saveProxyUrl as P,saveMem0ProxyUrl as C,getSessionToken as T,getUserInfo as z,clearSession as S,saveProjects as A}from"../config/config.js";function L(n){const o=process.platform;try{let t,r;return o==="darwin"?(t="open",r=[n]):o==="win32"?(t="cmd",r=["/c","start","",n]):(t="xdg-open",r=[n]),U(t,r,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function h(){const n=T(),o=z();return n&&o?{loggedIn:!0,user:o,token:n}:{loggedIn:!1}}async function Y(){try{console.log(e.cyan(`
1
+ import e from"chalk";import y from"ora";import{spawn as U}from"child_process";import{getApiUrl as p}from"../config/environments.js";import{saveSessionToken as $,saveUserInfo as x,saveProxyUrl as P,saveMem0ProxyUrl as C,getSessionToken as S,getUserInfo as A,clearSession as T,saveProjects as z}from"../config/config.js";import{clearActiveSkills as L}from"../commands/chat-session-store.js";function N(n){const o=process.platform;try{let t,r;return o==="darwin"?(t="open",r=[n]):o==="win32"?(t="cmd",r=["/c","start","",n]):(t="xdg-open",r=[n]),U(t,r,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function h(){const n=S(),o=A();return n&&o?{loggedIn:!0,user:o,token:n}:{loggedIn:!1}}async function G(){try{console.log(e.cyan(`
2
2
  \u{1F510} Initiating login...
3
3
  `));const n=h();if(n.loggedIn){console.log(e.green("\u2705 Already logged in!")),console.log(e.gray(`User: ${n.user.email}`)),console.log(e.gray(`Name: ${n.user.name}
4
4
  `));const{createInterface:o}=await import("readline"),t=o({input:process.stdin,output:process.stdout});return new Promise((r,c)=>{const s=()=>{t.close(),process.stdin.isTTY&&process.stdin.setRawMode(!1)},i=()=>{console.log(e.yellow(`
5
5
 
6
6
  \u26A0\uFE0F Login cancelled
7
7
  `)),s(),process.exit(0)};process.on("SIGINT",i),t.question(e.yellow("Continue with this session? (Y/n): "),async a=>{process.removeListener("SIGINT",i),s();try{if(a.toLowerCase()==="n"||a.toLowerCase()==="no"){console.log(e.gray(`Starting new login...
8
- `));const d=await I();r(d)}else console.log(e.green(`Using existing session.
9
- `)),r({success:!0,...n})}catch(d){c(d)}})})}return await I()}catch(n){return console.error(e.red(`
10
- \u274C Login failed:`,n.message)),{success:!1,error:n.message}}}async function N(n){const o=p();try{const t=await fetch(`${o}/projects`,{headers:{Authorization:`Bearer ${n}`}});if(t.ok){const c=((await t.json()).projects||[]).map(s=>({name:s.name,projectId:s.projectId,apiToken:s.apiToken}));return A(c),c}}catch(t){console.log(e.gray(`\u26A0\uFE0F Could not fetch projects: ${t.message}`))}return[]}async function I(){const n=p(),o=y("Requesting login code...").start(),t=await fetch(`${n}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!t.ok){o.fail("Failed to request login code");const u=await t.json();throw new Error(u.error||"Failed to initiate login")}const{deviceCode:r,userCode:c,verificationUrl:s,expiresIn:i,interval:a}=await t.json();o.succeed("Login code generated"),console.log(""),console.log(e.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(e.cyan("\u2551")+e.white.bold(" Complete login in your browser ")+e.cyan("\u2551")),console.log(e.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(e.white("Opening browser to login page...")),console.log(e.gray(`Code expires in ${Math.floor(i/60)} minutes`)),console.log(""),await L(s)||(console.log(e.yellow("\u26A0\uFE0F Could not open browser automatically.")),console.log(e.white("Please open this URL manually: ")+e.blue(s)),console.log(""));const g=y("Waiting for authorization...").start(),v=(a||3)*1e3,b=Math.floor(i/(a||3));let w=0,m=!1;const k=()=>{m=!0,g.stop(),console.log(e.yellow(`
8
+ `));const d=await v();r(d)}else console.log(e.green(`Using existing session.
9
+ `)),r({success:!0,...n})}catch(d){c(d)}})})}return await v()}catch(n){return console.error(e.red(`
10
+ \u274C Login failed:`,n.message)),{success:!1,error:n.message}}}async function E(n){const o=p();try{const t=await fetch(`${o}/projects`,{headers:{Authorization:`Bearer ${n}`}});if(t.ok){const c=((await t.json()).projects||[]).map(s=>({name:s.name,projectId:s.projectId,apiToken:s.apiToken}));return z(c),c}}catch(t){console.log(e.gray(`\u26A0\uFE0F Could not fetch projects: ${t.message}`))}return[]}async function v(){const n=p(),o=y("Requesting login code...").start(),t=await fetch(`${n}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!t.ok){o.fail("Failed to request login code");const u=await t.json();throw new Error(u.error||"Failed to initiate login")}const{deviceCode:r,userCode:c,verificationUrl:s,expiresIn:i,interval:a}=await t.json();o.succeed("Login code generated"),console.log(""),console.log(e.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(e.cyan("\u2551")+e.white.bold(" Complete login in your browser ")+e.cyan("\u2551")),console.log(e.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(e.white("Opening browser to login page...")),console.log(e.gray(`Code expires in ${Math.floor(i/60)} minutes`)),console.log(""),await N(s)||(console.log(e.yellow("\u26A0\uFE0F Could not open browser automatically.")),console.log(e.white("Please open this URL manually: ")+e.blue(s)),console.log(""));const g=y("Waiting for authorization...").start(),I=(a||3)*1e3,b=Math.floor(i/(a||3));let w=0,m=!1;const k=()=>{m=!0,g.stop(),console.log(e.yellow(`
11
11
 
12
12
  \u26A0\uFE0F Login cancelled
13
- `)),process.exit(0)};process.on("SIGINT",k);try{for(;w<b&&!m;){await E(v),w++;const u=await fetch(`${n}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:r})});if(u.status===202)continue;if(!u.ok){g.fail("Authorization failed");const f=await u.json();throw new Error(f.error||"Authorization failed")}const l=await u.json();if(l.status==="authorized"){g.succeed(e.white("Authorization successful!")),$(l.token),x(l.user),l.proxyUrl&&P(l.proxyUrl),l.mem0ProxyUrl&&C(l.mem0ProxyUrl),console.log(""),console.log(e.gray(`User: ${l.user.email}`));const f=y("Fetching projects...").start(),j=await N(l.token);return f.succeed(`Fetched ${j.length} project${j.length!==1?"s":""}`),console.log(e.gray(`Session saved to: ~/.zibby/config.json
14
- `)),{success:!0,loggedIn:!0,user:l.user,token:l.token}}if(l.status==="denied")throw g.fail("Authorization denied"),new Error("User denied authorization")}throw g.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",k)}}function F(){if(!h().loggedIn){console.log(e.yellow(`
13
+ `)),process.exit(0)};process.on("SIGINT",k);try{for(;w<b&&!m;){await B(I),w++;const u=await fetch(`${n}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:r})});if(u.status===202)continue;if(!u.ok){g.fail("Authorization failed");const f=await u.json();throw new Error(f.error||"Authorization failed")}const l=await u.json();if(l.status==="authorized"){g.succeed(e.white("Authorization successful!")),$(l.token),x(l.user),l.proxyUrl&&P(l.proxyUrl),l.mem0ProxyUrl&&C(l.mem0ProxyUrl),console.log(""),console.log(e.gray(`User: ${l.user.email}`));const f=y("Fetching projects...").start(),j=await E(l.token);return f.succeed(`Fetched ${j.length} project${j.length!==1?"s":""}`),console.log(e.gray(`Session saved to: ~/.zibby/config.json
14
+ `)),{success:!0,loggedIn:!0,user:l.user,token:l.token}}if(l.status==="denied")throw g.fail("Authorization denied"),new Error("User denied authorization")}throw g.fail("Login timeout"),new Error("Login timed out - please try again")}finally{process.removeListener("SIGINT",k)}}function J(){if(!h().loggedIn){console.log(e.yellow(`
15
15
  \u26A0\uFE0F Not logged in.
16
- `));return}S(),console.log(e.green("\u2714")+e.white(" Logged out successfully!")),console.log(e.gray(`Session cleared from ~/.zibby/config.json
17
- `))}async function G(n={}){const o=h(),t=process.env.ZIBBY_USER_TOKEN,r=p(),c=t||o.token;if(n.json){const s={authenticated:!!(o.loggedIn||t),user:o.user||null,tokenSource:t?"environment":o.token?"session":null,tokenType:t?"PAT":o.token?"JWT":null,apiUrl:r,configPath:o.loggedIn?"~/.zibby/config.json":null};if(c)try{const i=await fetch(`${r}/projects`,{headers:{Authorization:`Bearer ${c}`}});if(s.tokenValid=i.ok,i.ok){const a=await i.json();s.projectCount=(a.projects||[]).length}}catch(i){s.tokenValid=!1,s.error=i.message}else s.tokenValid=!1;console.log(JSON.stringify(s,null,2));return}if(console.log(""),!o.loggedIn&&!t){console.log(e.yellow("\u26A0\uFE0F Not authenticated")),console.log(""),console.log(e.white("To authenticate:")),console.log(e.gray(" Local: zibby login")),console.log(e.gray(` CI/CD: Set ZIBBY_USER_TOKEN env variable
18
- `));return}if(console.log(e.green("\u2705 Authenticated")),console.log(""),console.log(e.bold.white("User Details:")),o.user?(console.log(e.gray(` Email: ${o.user.email}`)),o.user.userId&&console.log(e.gray(` User ID: ${o.user.userId}`)),o.user.name&&console.log(e.gray(` Name: ${o.user.name}`))):t&&console.log(e.gray(" (User details not available with PAT token)")),console.log(""),console.log(e.bold.white("Token Source:")),t?(console.log(e.gray(" Type: Personal Access Token (PAT)")),console.log(e.gray(" Location: ZIBBY_USER_TOKEN environment variable")),console.log(e.gray(` Preview: ${t.substring(0,8)}\u2022\u2022\u2022\u2022`))):(console.log(e.gray(" Type: Session Token (JWT)")),console.log(e.gray(" Location: ~/.zibby/config.json")),o.token&&console.log(e.gray(` Preview: ${o.token.substring(0,8)}\u2022\u2022\u2022\u2022`))),console.log(""),c)try{const s=(await import("ora")).default,i=s("Verifying authentication...").start(),a=await fetch(`${r}/projects`,{headers:{Authorization:`Bearer ${c}`}});if(a.ok){const g=((await a.json()).projects||[]).length;i.succeed(e.white("Token verified")),console.log(e.gray(` Projects: ${g} accessible`))}else i.fail(e.white("Token verification failed")),console.log(e.yellow(` Status: Invalid or expired (HTTP ${a.status})`))}catch(s){console.log(e.yellow(` Status: Could not verify (${s.message})`))}console.log(""),console.log(e.gray("\u{1F4A1} Run 'zibby list' to see your projects")),console.log("")}async function J(){const n=T();if(!n)return{valid:!1};const o=p();try{return(await fetch(`${o}/projects`,{headers:{Authorization:`Bearer ${n}`}})).ok?{valid:!0}:(S(),{valid:!1})}catch{return{valid:!1}}}function E(n){return new Promise(o=>setTimeout(o,n))}export{h as checkExistingSession,Y as loginCli,F as logoutCli,G as showLoginStatus,J as validateSession};
16
+ `));return}T(),L(),console.log(e.green("\u2714")+e.white(" Logged out successfully!")),console.log(e.gray(`Session cleared from ~/.zibby/config.json
17
+ `))}async function M(n={}){const o=h(),t=process.env.ZIBBY_USER_TOKEN,r=p(),c=t||o.token;if(n.json){const s={authenticated:!!(o.loggedIn||t),user:o.user||null,tokenSource:t?"environment":o.token?"session":null,tokenType:t?"PAT":o.token?"JWT":null,apiUrl:r,configPath:o.loggedIn?"~/.zibby/config.json":null};if(c)try{const i=await fetch(`${r}/projects`,{headers:{Authorization:`Bearer ${c}`}});if(s.tokenValid=i.ok,i.ok){const a=await i.json();s.projectCount=(a.projects||[]).length}}catch(i){s.tokenValid=!1,s.error=i.message}else s.tokenValid=!1;console.log(JSON.stringify(s,null,2));return}if(console.log(""),!o.loggedIn&&!t){console.log(e.yellow("\u26A0\uFE0F Not authenticated")),console.log(""),console.log(e.white("To authenticate:")),console.log(e.gray(" Local: zibby login")),console.log(e.gray(` CI/CD: Set ZIBBY_USER_TOKEN env variable
18
+ `));return}if(console.log(e.green("\u2705 Authenticated")),console.log(""),console.log(e.bold.white("User Details:")),o.user?(console.log(e.gray(` Email: ${o.user.email}`)),o.user.userId&&console.log(e.gray(` User ID: ${o.user.userId}`)),o.user.name&&console.log(e.gray(` Name: ${o.user.name}`))):t&&console.log(e.gray(" (User details not available with PAT token)")),console.log(""),console.log(e.bold.white("Token Source:")),t?(console.log(e.gray(" Type: Personal Access Token (PAT)")),console.log(e.gray(" Location: ZIBBY_USER_TOKEN environment variable")),console.log(e.gray(` Preview: ${t.substring(0,8)}\u2022\u2022\u2022\u2022`))):(console.log(e.gray(" Type: Session Token (JWT)")),console.log(e.gray(" Location: ~/.zibby/config.json")),o.token&&console.log(e.gray(` Preview: ${o.token.substring(0,8)}\u2022\u2022\u2022\u2022`))),console.log(""),c)try{const s=(await import("ora")).default,i=s("Verifying authentication...").start(),a=await fetch(`${r}/projects`,{headers:{Authorization:`Bearer ${c}`}});if(a.ok){const g=((await a.json()).projects||[]).length;i.succeed(e.white("Token verified")),console.log(e.gray(` Projects: ${g} accessible`))}else i.fail(e.white("Token verification failed")),console.log(e.yellow(` Status: Invalid or expired (HTTP ${a.status})`))}catch(s){console.log(e.yellow(` Status: Could not verify (${s.message})`))}console.log(""),console.log(e.gray("\u{1F4A1} Run 'zibby list' to see your projects")),console.log("")}async function V(){const n=S();if(!n)return{valid:!1};const o=p();try{return(await fetch(`${o}/projects`,{headers:{Authorization:`Bearer ${n}`}})).ok?{valid:!0}:(T(),{valid:!1})}catch{return{valid:!1}}}function B(n){return new Promise(o=>setTimeout(o,n))}export{h as checkExistingSession,G as loginCli,J as logoutCli,M as showLoginStatus,V as validateSession};
package/dist/bin/zibby.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- process.stdout.on("error",o=>{o.code}),process.stderr.on("error",o=>{o.code}),process.env.DOTENV_CONFIG_QUIET="true";import"@zibby/skills";import{Command as d}from"commander";import{initCommand as p}from"../commands/init.js";import{runCommand as m}from"../commands/run.js";import{videoCommand as l}from"../commands/video.js";import{uploadCommand as u}from"../commands/upload.js";import{ciSetupCommand as f}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as w,setupCiCommand as y,testWithVideoCommand as g}from"../commands/setup-scripts.js";import{readFileSync as h}from"fs";import{fileURLToPath as b}from"url";import{dirname as k,join as C}from"path";import{bootstrapAgentEnv as v}from"../utils/agent-credentials.js";const I=b(import.meta.url),P=k(I),r=JSON.parse(h(C(P,"../package.json"),"utf-8")),s=`zibby v${r.version}`,i=process.argv.slice(2),S=i.includes("-h")||i.includes("--help"),_=i.includes("-v")||i.includes("-V")||i.includes("--version");_&&(console.log(s),process.exit(0)),console.log(`${s}
3
- `),v(process.cwd());const j=i[0]==="chat",x=["--verbose","--agent","--stream","-s"],D=i.length>0&&i.every(o=>x.includes(o)||i[i.indexOf(o)-1]==="--agent"),E=i.length===0||j||D;if(E&&!S){const o={},t=i.indexOf("--agent");t!==-1&&i[t+1]&&(o.agent=i[t+1]),i.includes("--verbose")&&(o.verbose=!0),(i.includes("--stream")||i.includes("-s"))&&(o.stream=!0);const{chatCommand:n}=await import("../commands/chat.js");await n(o),process.exit(0)}const e=new d;e.name("zibby").description("Zibby Test Automation - AI-powered test generation").version(r.version,"-V, --version"),e.command("init").description("Initialize a new Zibby test project (like rails new)").argument("[project-name]","Project name (optional, uses current directory if not provided)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini)").option("--memory-backend <backend>","Memory backend to configure (dolt, mem0)","dolt").option("--skip-install","Skip npm install").option("--skip-memory","Skip test memory setup during initialization").option("-f, --force","Force reinitialize (overwrite existing config)").option("--headed","Run MCP browser in headed mode (visible browser)").option("--headless","Run MCP browser in headless mode (hidden browser)").option("--api-key <key>","Zibby API key for cloud sync").option("--cloud-sync","Enable cloud sync and install Zibby MCP").action(p),e.command("test").description("Run a test specification").argument("[spec-path]","Path to test spec file or inline test description in quotes").option("--sources <ids>","Comma-separated test case IDs to fetch from cloud").option("--execution <id>","Execution ID containing the test cases (required with --sources)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini) - overrides config").option("--workflow <name>","Workflow to use (e.g., QuickSmokeWorkflow, quick-smoke)").option("--headless","Run browser in headless mode").option("--node <name>","Run only a specific node (e.g., execute_live, generate_script)").option("--session <id>",'Use existing session (e.g., 1768974629717 or "last") - requires --node').option("--session-path <dir>","Use this session folder (absolute or relative to cwd); Studio pins artifacts here").option("--project <id>","Project ID (optional, auto-detected from ZIBBY_API_KEY)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional, requires --collection)").option("--sync","Force upload to cloud (overrides cloudSync: false)").option("--no-sync","Skip upload to cloud (overrides cloudSync: true)").option("--config <path>","Path to config file",".zibby.config.mjs").option("--auto-approve","Auto-approve MCP tools (for CI/CD)").option("-o, --open","Open test results in browser after completion").option("--verbose","Show info level logs").option("--debug","Show debug level logs (most verbose)").option("-m, --mem","Enable test memory (Dolt-backed knowledge from previous runs)").action((o,t)=>(t.debug?process.env.ZIBBY_DEBUG="true":t.verbose&&(process.env.ZIBBY_VERBOSE="true"),m(o,t))),e.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...o)=>{const{implementCommand:t}=await import("../commands/implement.js");return t(...o)}),e.command("analyze").description("Analyze a Jira ticket against the codebase (runs in ECS container)").option("--workflow <path>","Path to a local workflow JSON file (e.g., .zibby/workflow-analysis.json)").action(async(...o)=>{const{analyzeCommand:t}=await import("../commands/analyze-graph.js");return t(...o)}),e.command("video").description("Organize test videos next to test files").action(l),e.command("upload <spec-path>").description("Upload existing test artifacts to Zibby Cloud").option("--project <id>","Project ID (REQUIRED - use flag or ZIBBY_PROJECT_ID env)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional)").option("--agent <type>","Agent used (for metadata)").action(u),e.command("login").description("Log in to Zibby (opens browser for authentication)").action(async()=>{const{loginCli:o}=await import("../auth/cli-login.js");await o(),process.exit(0)}),e.command("logout").description("Log out from Zibby (clears saved session)").action(async()=>{const{logoutCli:o}=await import("../auth/cli-login.js");o(),process.exit(0)}),e.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async o=>{const{showLoginStatus:t}=await import("../auth/cli-login.js");await t(o),process.exit(0)}),e.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:o}=await import("../commands/list-projects.js");await o()}),e.command("ci-setup").description("Setup Cursor Agent for CI/CD (patch and configure)").option("--get-keys","Get MCP approval keys").option("--save","Save approval keys to project").action(f),e.command("setup-playwright").description("Setup official Playwright MCP (from cursor-agent-package)").option("--headed","Configure MCP in headed mode (visible browser)").option("--viewport-width <width>","Viewport width (default: 1280)","1280").option("--viewport-height <height>","Viewport height (default: 720)","720").action(o=>{const t={width:parseInt(o.viewportWidth,10)||1280,height:parseInt(o.viewportHeight,10)||720};return w({...o,viewport:t})}),e.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(y),e.command("test-video").description("Run Playwright tests with video recording").argument("[test-file]","Test file to run (default: tests/)").option("--headed","Run in headed mode (visible browser)").action(g),e.command("generate").description("Generate test specs from a ticket + codebase (local analysis using real AI agent)").option("-t, --ticket <key>","Jira ticket key (fetches automatically)").option("-i, --input <file>","Input file with ticket description/requirements").option("-d, --description <text>","Inline ticket description").option("--repo <path>","Path to the codebase (default: current directory)").option("--agent <type>","Agent to use (codex, claude, cursor, gemini)").option("--model <model>","Model override").option("-o, --output <dir>","Output directory for spec files (default: test-specs)").action(async o=>{const{generateCommand:t}=await import("../commands/generate.js");return t(o)}),e.command("studio").description("Launch Zibby Studio desktop (installs from CDN if needed). Uses this folder as the Zibby project.").option("-p, --port <port>","Port for the Studio API bridge (default: 3847)").option("--no-open","Start the API only; do not launch desktop app").option("--update","Force re-download of the latest Studio binary").action(async o=>{const{studioCommand:t}=await import("../commands/studio.js");return t(o)});const A=e.command("g").description("Generate scaffolds");A.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").action(async o=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(o)}),e.command("start <workflow-name>").description("Start a local dev server for a custom workflow").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(o,t)=>{const{startWorkflowCommand:n}=await import("../commands/workflows/start.js");return n(o,t)}),e.command("deploy <workflow-name>").description("Deploy a custom workflow to Zibby Cloud").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(o,t)=>{const{deployWorkflowCommand:n}=await import("../commands/workflows/deploy.js");return n(o,t)}),e.command("logs [jobId]").description("Tail logs from a workflow job (use --workflow to auto-pick latest)").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (tails the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--no-follow","Fetch logs once and exit (default: tail)").option("--lines <n>","Max log lines per fetch (default: 200)").action(async(o,t)=>{const{logsCommand:n}=await import("../commands/workflows/logs.js");return n(o,t)}),e.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:o}=await import("../commands/workflows/run.js");return o()});const a=e.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");a.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:o}=await import("../commands/memory.js");return o()}),a.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:o}=await import("../commands/memory.js");return o()}),a.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async o=>{const{memoryCompactCommand:t}=await import("../commands/memory.js");return t(o)}),a.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async o=>{const{memoryResetCommand:t}=await import("../commands/memory.js");return t(o)});const c=e.command("workflow").description("Manage workflow graphs (download, upload, list)");c.command("download").description("Download a workflow graph from Zibby Cloud to .zibby/").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--type <type>","Workflow type: analysis, implementation, run_test").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--output <dir>","Output directory (default: .zibby/)").option("--include-default","Download the built-in default graph if no custom one exists").action(async o=>{const{workflowDownloadCommand:t}=await import("../commands/workflow.js");return t(o)}),c.command("list").description("List all workflows for a project").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{const{workflowListCommand:t}=await import("../commands/workflow.js");return t(o)});const B=e.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");B.command("list").description("List CLI processes waiting for a run slot").option("--config <path>","Path to config file",".zibby.config.mjs").action(async o=>{const{runCapacityQueueListCommand:t}=await import("../commands/run-capacity-queue-cli.js");await t(o),process.exit(0)}),e.command("uninstall").description("Remove all Zibby data: global CLI, ~/.zibby, Cursor MCP config, Studio, and current project").option("--dry-run","Show what would be deleted without deleting").option("--deep","Also remove npx cache dirs containing zibby").action(async o=>{const{uninstallCommand:t}=await import("../commands/uninstall.js");await t(o),process.exit(0)}),e.parse();
2
+ process.stdout.on("error",o=>{o.code}),process.stderr.on("error",o=>{o.code}),process.env.DOTENV_CONFIG_QUIET="true";import"@zibby/skills";import{Command as p}from"commander";import{initCommand as d}from"../commands/init.js";import{runCommand as l}from"../commands/run.js";import{videoCommand as m}from"../commands/video.js";import{uploadCommand as u}from"../commands/upload.js";import{ciSetupCommand as f}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as w,setupCiCommand as y,testWithVideoCommand as g}from"../commands/setup-scripts.js";import{readFileSync as h}from"fs";import{fileURLToPath as k}from"url";import{dirname as b,join as v}from"path";import{bootstrapAgentEnv as C}from"../utils/agent-credentials.js";const I=k(import.meta.url),P=b(I),r=JSON.parse(h(v(P,"../package.json"),"utf-8")),s=`zibby v${r.version}`,i=process.argv.slice(2),j=i.includes("-h")||i.includes("--help"),S=i.includes("-v")||i.includes("-V")||i.includes("--version");S&&(console.log(s),process.exit(0)),console.log(`${s}
3
+ `),C(process.cwd());const _=i[0]==="chat",x=["--verbose","--agent","--stream","-s"],A=i.length>0&&i.every(o=>x.includes(o)||i[i.indexOf(o)-1]==="--agent"),B=i.length===0||_||A;if(B&&!j){const o={},t=i.indexOf("--agent");t!==-1&&i[t+1]&&(o.agent=i[t+1]),i.includes("--verbose")&&(o.verbose=!0),(i.includes("--stream")||i.includes("-s"))&&(o.stream=!0);const{chatCommand:n}=await import("../commands/chat.js");await n(o),process.exit(0)}const e=new p;e.name("zibby").description("Zibby Test Automation - AI-powered test generation").version(r.version,"-V, --version"),e.command("init").description("Initialize a new Zibby test project (like rails new)").argument("[project-name]","Project name (optional, uses current directory if not provided)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini)").option("--memory-backend <backend>","Memory backend to configure (dolt, mem0)","dolt").option("--skip-install","Skip npm install").option("--skip-memory","Skip test memory setup during initialization").option("-f, --force","Force reinitialize (overwrite existing config)").option("--headed","Run MCP browser in headed mode (visible browser)").option("--headless","Run MCP browser in headless mode (hidden browser)").option("--api-key <key>","Zibby API key for cloud sync").option("--cloud-sync","Enable cloud sync and install Zibby MCP").action(d),e.command("test").description("Run a test specification").argument("[spec-path]","Path to test spec file or inline test description in quotes").option("--sources <ids>","Comma-separated test case IDs to fetch from cloud").option("--execution <id>","Execution ID containing the test cases (required with --sources)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini) - overrides config").option("--workflow <name>","Workflow to use (e.g., QuickSmokeWorkflow, quick-smoke)").option("--headless","Run browser in headless mode").option("--node <name>","Run only a specific node (e.g., execute_live, generate_script)").option("--session <id>",'Use existing session (e.g., 1768974629717 or "last") - requires --node').option("--session-path <dir>","Use this session folder (absolute or relative to cwd); Studio pins artifacts here").option("--project <id>","Project ID (optional, auto-detected from ZIBBY_API_KEY)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional, requires --collection)").option("--sync","Force upload to cloud (overrides cloudSync: false)").option("--no-sync","Skip upload to cloud (overrides cloudSync: true)").option("--config <path>","Path to config file",".zibby.config.mjs").option("--auto-approve","Auto-approve MCP tools (for CI/CD)").option("-o, --open","Open test results in browser after completion").option("--verbose","Show info level logs").option("--debug","Show debug level logs (most verbose)").option("-m, --mem","Enable test memory (Dolt-backed knowledge from previous runs)").action((o,t)=>(t.debug?process.env.ZIBBY_DEBUG="true":t.verbose&&(process.env.ZIBBY_VERBOSE="true"),l(o,t))),e.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...o)=>{const{implementCommand:t}=await import("../commands/implement.js");return t(...o)}),e.command("analyze").description("Analyze a Jira ticket against the codebase (runs in ECS container)").option("--workflow <path>","Path to a local workflow JSON file (e.g., .zibby/workflow-analysis.json)").action(async(...o)=>{const{analyzeCommand:t}=await import("../commands/analyze-graph.js");return t(...o)}),e.command("video").description("Organize test videos next to test files").action(m),e.command("upload <spec-path>").description("Upload existing test artifacts to Zibby Cloud").option("--project <id>","Project ID (REQUIRED - use flag or ZIBBY_PROJECT_ID env)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional)").option("--agent <type>","Agent used (for metadata)").action(u),e.command("login").description("Log in to Zibby (opens browser for authentication)").action(async()=>{const{loginCli:o}=await import("../auth/cli-login.js");await o(),process.exit(0)}),e.command("logout").description("Log out from Zibby (clears saved session)").action(async()=>{const{logoutCli:o}=await import("../auth/cli-login.js");o(),process.exit(0)}),e.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async o=>{const{showLoginStatus:t}=await import("../auth/cli-login.js");await t(o),process.exit(0)}),e.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:o}=await import("../commands/list-projects.js");await o()}),e.command("ci-setup").description("Setup Cursor Agent for CI/CD (patch and configure)").option("--get-keys","Get MCP approval keys").option("--save","Save approval keys to project").action(f),e.command("setup-playwright").description("Setup official Playwright MCP (from cursor-agent-package)").option("--headed","Configure MCP in headed mode (visible browser)").option("--viewport-width <width>","Viewport width (default: 1280)","1280").option("--viewport-height <height>","Viewport height (default: 720)","720").action(o=>{const t={width:parseInt(o.viewportWidth,10)||1280,height:parseInt(o.viewportHeight,10)||720};return w({...o,viewport:t})}),e.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(y),e.command("test-video").description("Run Playwright tests with video recording").argument("[test-file]","Test file to run (default: tests/)").option("--headed","Run in headed mode (visible browser)").action(g),e.command("generate").description("Generate test specs from a ticket + codebase (local analysis using real AI agent)").option("-t, --ticket <key>","Jira ticket key (fetches automatically)").option("-i, --input <file>","Input file with ticket description/requirements").option("-d, --description <text>","Inline ticket description").option("--repo <path>","Path to the codebase (default: current directory)").option("--agent <type>","Agent to use (codex, claude, cursor, gemini)").option("--model <model>","Model override").option("-o, --output <dir>","Output directory for spec files (default: test-specs)").action(async o=>{const{generateCommand:t}=await import("../commands/generate.js");return t(o)}),e.command("studio").description("Launch Zibby Studio desktop (installs from CDN if needed). Uses this folder as the Zibby project.").option("-p, --port <port>","Port for the Studio API bridge (default: 3847)").option("--no-open","Start the API only; do not launch desktop app").option("--update","Force re-download of the latest Studio binary").action(async o=>{const{studioCommand:t}=await import("../commands/studio.js");return t(o)});const E=e.command("g").description("Generate scaffolds");E.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").action(async o=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(o)}),e.command("start <workflow-name>").description("Start a local dev server for a custom workflow").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(o,t)=>{const{startWorkflowCommand:n}=await import("../commands/workflows/start.js");return n(o,t)}),e.command("deploy [workflow-name]").description("Deploy a custom workflow to Zibby Cloud (interactive selection if workflow-name not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(o,t)=>{const{deployWorkflowCommand:n}=await import("../commands/workflows/deploy.js");return n(o,t)}),e.command("trigger [workflow-name]").description("Trigger a deployed workflow to run in the cloud (interactive selection if not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--input <json>",`Input data as JSON string (e.g., '{"key":"value"}')`).option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").action(async(o,t)=>{const{triggerWorkflowCommand:n}=await import("../commands/workflows/trigger.js");return n(o,t)}),e.command("logs [jobId]").description("Tail logs from a workflow job or all executions of a workflow").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (tails the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --tail-latest","Auto-tail newest execution (scrollable history)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--no-follow","Fetch logs once and exit (default: tail)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(o,t)=>{const{logsCommand:n}=await import("../commands/workflows/logs.js");return n(o,t)}),e.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:o}=await import("../commands/workflows/run.js");return o()});const a=e.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");a.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:o}=await import("../commands/memory.js");return o()}),a.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:o}=await import("../commands/memory.js");return o()}),a.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async o=>{const{memoryCompactCommand:t}=await import("../commands/memory.js");return t(o)}),a.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async o=>{const{memoryResetCommand:t}=await import("../commands/memory.js");return t(o)});const c=e.command("workflow").description("Manage workflow graphs (download, upload, list)");c.command("download").description("Download a workflow graph from Zibby Cloud to .zibby/").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--type <type>","Workflow type: analysis, implementation, run_test").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--output <dir>","Output directory (default: .zibby/)").option("--include-default","Download the built-in default graph if no custom one exists").action(async o=>{const{workflowDownloadCommand:t}=await import("../commands/workflow.js");return t(o)}),c.command("list").description("List all workflows (local + remote if credentials available)").option("--local-only","Show only local workflows").option("--remote-only","Show only remote workflows (requires --project)").option("--project <id>","Project ID (optional, uses ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{if(o.remoteOnly){const{workflowListCommand:n}=await import("../commands/workflow.js");return n(o)}if(o.localOnly){const{listLocalWorkflowsCommand:n}=await import("../commands/workflows/list.js");return n(o)}const{listAllWorkflowsCommand:t}=await import("../commands/workflows/list.js");return t(o)});const D=e.command("project").description("Manage Zibby projects");D.command("list").description("List all projects").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{const{projectListCommand:t}=await import("../commands/project.js");return t(o)});const Z=e.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");Z.command("list").description("List CLI processes waiting for a run slot").option("--config <path>","Path to config file",".zibby.config.mjs").action(async o=>{const{runCapacityQueueListCommand:t}=await import("../commands/run-capacity-queue-cli.js");await t(o),process.exit(0)}),e.command("uninstall").description("Remove all Zibby data: global CLI, ~/.zibby, Cursor MCP config, Studio, and current project").option("--dry-run","Show what would be deleted without deleting").option("--deep","Also remove npx cache dirs containing zibby").action(async o=>{const{uninstallCommand:t}=await import("../commands/uninstall.js");await t(o),process.exit(0)}),e.parse();
@@ -1 +1 @@
1
- import{existsSync as o,mkdirSync as a,readFileSync as u,writeFileSync as c}from"fs";import{resolve as s}from"path";const y=30;function e(r){const t=s(r,".zibby","output");return o(t)||a(t,{recursive:!0}),t}function f(r){const t=s(r,".zibby","output","chat-history.json");if(!o(t))return[];try{const i=JSON.parse(u(t,"utf-8"));return Array.isArray(i)?i:[]}catch{return[]}}function h(r,t){const i=e(r),n=s(i,"chat-history.json");try{c(n,JSON.stringify((t||[]).slice(-y*2),null,2),"utf-8")}catch{}}function S(r){const t=s(r,".zibby","output","active-skills.json");if(!o(t))return null;try{const i=JSON.parse(u(t,"utf-8"));return Array.isArray(i)?i:null}catch{return null}}function A(r,t){const i=e(r),n=s(i,"active-skills.json");try{c(n,JSON.stringify(Array.isArray(t)?t:[]),"utf-8")}catch{}}export{S as loadActiveSkills,f as loadChatHistory,A as saveActiveSkills,h as saveChatHistory};
1
+ import{existsSync as o,mkdirSync as a,readFileSync as c,writeFileSync as u,unlinkSync as l}from"fs";import{resolve as s}from"path";import{homedir as y}from"os";const p=30;function e(r){const t=s(r,".zibby","output");return o(t)||a(t,{recursive:!0}),t}function v(r){const t=s(r,".zibby","output","chat-history.json");if(!o(t))return[];try{const i=JSON.parse(c(t,"utf-8"));return Array.isArray(i)?i:[]}catch{return[]}}function b(r,t){const i=e(r),n=s(i,"chat-history.json");try{u(n,JSON.stringify((t||[]).slice(-p*2),null,2),"utf-8")}catch{}}function d(r){const t=s(r,".zibby","output","active-skills.json");if(!o(t))return null;try{const i=JSON.parse(c(t,"utf-8"));return Array.isArray(i)?i:null}catch{return null}}function k(r,t){const i=e(r),n=s(i,"active-skills.json");try{u(n,JSON.stringify(Array.isArray(t)?t:[]),"utf-8")}catch{}}function A(){const r=[s(process.cwd(),".zibby","output","active-skills.json"),s(y(),".zibby","output","active-skills.json")];for(const t of r)try{o(t)&&l(t)}catch{}}export{A as clearActiveSkills,d as loadActiveSkills,v as loadChatHistory,k as saveActiveSkills,b as saveChatHistory};
@@ -1,58 +1,58 @@
1
- import{invokeAgent as xe,getAgentStrategy as ve,getSkill as $t}from"@zibby/core";import{existsSync as gt,readFileSync as oe,readdirSync as Te}from"fs";import{resolve as lt,join as Dt,dirname as Ce,basename as Ie}from"path";import{createInterface as Pe,moveCursor as M,cursorTo as B,clearLine as G,emitKeypressEvents as Ae}from"readline";import{fileURLToPath as Ee}from"url";import{homedir as Le}from"os";import e from"chalk";import{highlight as ne}from"cli-highlight";import Me from"dotenv";import{getSessionToken as Wt,getUserInfo as Ne,getProjects as Oe,saveSessionToken as Be,saveUserInfo as Re,clearSession as Ue,saveProxyUrl as Fe,getProxyUrl as je,getMem0ProxyUrl as De,saveMem0ProxyUrl as We}from"../config/config.js";import{getApiUrl as re}from"../config/environments.js";import{loadActiveSkills as Ye,loadChatHistory as He,saveActiveSkills as It,saveChatHistory as Pt}from"./chat-session-store.js";import{buildReliabilityInstruction as ze}from"./agent-reliability.js";const Je=Ee(import.meta.url),Ge=Ce(Je),qe=JSON.parse(oe(Dt(Ge,"../../package.json"),"utf-8")),ie=30,Ze=54,Ke=18e3,ce=12e3,ae=42e3;function Ve(o){return new Promise(t=>setTimeout(t,o))}const At=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Yt=[{cmd:"/help",desc:"Show this help"},{cmd:"/skills",desc:"List active & available skills"},{cmd:"/history",desc:"Show conversation history (--all or -n 50)"},{cmd:"/clear",desc:"Clear conversation history"},{cmd:"/memory",desc:"View stored memories, tasks, sessions"},{cmd:"/exit",desc:"Exit the chat"},{cmd:"/quit",desc:"Exit the chat"}];function le(){let o=0,t="thinking...";const s=setInterval(()=>{const l=e.cyan(At[o%At.length]),k=o%3,v=k===0?e.white(".")+e.gray(".")+e.dim("."):k===1?e.dim(".")+e.white(".")+e.gray("."):e.gray(".")+e.dim(".")+e.white("."),C=t.replace(/\.+$/,""),I=` ${l} ${e.gray(C)}${v}`;process.stdout.write(`\r${" ".repeat(80)}\r${I}`),o++},300),r=()=>{clearInterval(s),process.stdout.write(`\r${" ".repeat(80)}\r`)};return r.setLabel=l=>{t=l},r}function Us(o){const t=o?.agent;return t?t.provider?t.provider:t.gemini?"gemini":t.codex?"codex":t.claude?"claude":t.cursor?"cursor":process.env.AGENT_TYPE||"cursor":process.env.AGENT_TYPE||"cursor"}function Xe(o){return o.slice(-ie).map(t=>`${t.role==="human"?"H":"AI"}: ${t.content}`).join(`
1
+ import{invokeAgent as _e,getAgentStrategy as ve,getSkill as $t}from"@zibby/core";import{existsSync as gt,readFileSync as oe,readdirSync as Te}from"fs";import{resolve as ut,join as Dt,dirname as Ce,basename as Ie}from"path";import{createInterface as Pe,moveCursor as M,cursorTo as B,clearLine as q,emitKeypressEvents as Ae}from"readline";import{fileURLToPath as Ee}from"url";import{homedir as Le}from"os";import e from"chalk";import{highlight as ne}from"cli-highlight";import Me from"dotenv";import{getSessionToken as Wt,getUserInfo as Ne,getProjects as Oe,saveSessionToken as Be,saveUserInfo as Re,clearSession as Ue,saveProxyUrl as Fe,getProxyUrl as je,getMem0ProxyUrl as De,saveMem0ProxyUrl as We}from"../config/config.js";import{getApiUrl as re}from"../config/environments.js";import{loadActiveSkills as Ye,loadChatHistory as He,saveActiveSkills as It,saveChatHistory as Pt}from"./chat-session-store.js";import{buildReliabilityInstruction as ze}from"./agent-reliability.js";const Je=Ee(import.meta.url),Ge=Ce(Je),qe=JSON.parse(oe(Dt(Ge,"../../package.json"),"utf-8")),ie=30,Ze=54,Ke=18e3,ce=12e3,ae=42e3;function Ve(o){return new Promise(t=>setTimeout(t,o))}const At=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Yt=[{cmd:"/help",desc:"Show this help"},{cmd:"/skills",desc:"List active & available skills"},{cmd:"/history",desc:"Show conversation history (--all or -n 50)"},{cmd:"/clear",desc:"Clear conversation history"},{cmd:"/memory",desc:"View stored memories, tasks, sessions"},{cmd:"/exit",desc:"Exit the chat"},{cmd:"/quit",desc:"Exit the chat"}];function le(){let o=0,t="thinking...";const s=setInterval(()=>{const l=e.cyan(At[o%At.length]),k=o%3,v=k===0?e.white(".")+e.gray(".")+e.dim("."):k===1?e.dim(".")+e.white(".")+e.gray("."):e.gray(".")+e.dim(".")+e.white("."),C=t.replace(/\.+$/,""),I=` ${l} ${e.gray(C)}${v}`;process.stdout.write(`\r${" ".repeat(80)}\r${I}`),o++},300),r=()=>{clearInterval(s),process.stdout.write(`\r${" ".repeat(80)}\r`)};return r.setLabel=l=>{t=l},r}function Us(o){const t=o?.agent;return t?t.provider?t.provider:t.gemini?"gemini":t.codex?"codex":t.claude?"claude":t.cursor?"cursor":process.env.AGENT_TYPE||"cursor":process.env.AGENT_TYPE||"cursor"}function Xe(o){return o.slice(-ie).map(t=>`${t.role==="human"?"H":"AI"}: ${t.content}`).join(`
2
2
  `)}function Fs(o,t,s){let r=o;return t.length>0&&(r+=`
3
3
 
4
4
  ${Xe(t)}`),r+=`
5
5
  H: ${s}
6
- AI:`,r}function Qe(o){const t=o.filter(s=>!process.env[s]);return{ok:t.length===0,missing:t}}function ts(o){const t=lt(o,".zibby.config.mjs");if(!gt(t))return{};try{return import(t).then(s=>s.default||{})}catch{return{}}}async function es(o){const t=lt(o,".zibby","chat.mjs");if(gt(t)){const l=await import(t);if(l.CHAT_CONFIG||l.default)return l.CHAT_CONFIG||l.default}const s=lt(Le(),".zibby","chat.mjs");if(s!==t&&gt(s)){const l=await import(s);if(l.CHAT_CONFIG||l.default)return l.CHAT_CONFIG||l.default}const r=await import("@zibby/core/templates/browser-test-automation/chat.mjs");return r.CHAT_CONFIG||r.default||{}}function ue(o){try{const t=lt(o,".zibby","commands");return gt(t)?Te(t).filter(s=>s.toLowerCase().endsWith(".md")).sort((s,r)=>s.localeCompare(r)):[]}catch{return[]}}function ss(o,t){const s=String(t||"").trim();if(!s.startsWith("/"))return s;const[r,...l]=s.split(/\s+/),k=l.join(" ").trim(),v=r.slice(1);if(!v)return s;const C=v.toLowerCase().endsWith(".md")?[v]:[v,`${v}.md`],I=lt(o,".zibby","commands"),U=C.find(R=>gt(Dt(I,R)));if(!U)return s;try{const R=oe(Dt(I,U),"utf-8").trim();return k?`${R}
6
+ AI:`,r}function Qe(o){const t=o.filter(s=>!process.env[s]);return{ok:t.length===0,missing:t}}function ts(o){const t=ut(o,".zibby.config.mjs");if(!gt(t))return{};try{return import(t).then(s=>s.default||{})}catch{return{}}}async function es(o){const t=ut(o,".zibby","chat.mjs");if(gt(t)){const l=await import(t);if(l.CHAT_CONFIG||l.default)return l.CHAT_CONFIG||l.default}const s=ut(Le(),".zibby","chat.mjs");if(s!==t&&gt(s)){const l=await import(s);if(l.CHAT_CONFIG||l.default)return l.CHAT_CONFIG||l.default}const r=await import("@zibby/core/templates/browser-test-automation/chat.mjs");return r.CHAT_CONFIG||r.default||{}}function ue(o){try{const t=ut(o,".zibby","commands");return gt(t)?Te(t).filter(s=>s.toLowerCase().endsWith(".md")).sort((s,r)=>s.localeCompare(r)):[]}catch{return[]}}function ss(o,t){const s=String(t||"").trim();if(!s.startsWith("/"))return s;const[r,...l]=s.split(/\s+/),k=l.join(" ").trim(),v=r.slice(1);if(!v)return s;const C=v.toLowerCase().endsWith(".md")?[v]:[v,`${v}.md`],I=ut(o,".zibby","commands"),U=C.find(R=>gt(Dt(I,R)));if(!U)return s;try{const R=oe(Dt(I,U),"utf-8").trim();return k?`${R}
7
7
 
8
- ${k}`:R}catch{return s}}function os(o){const t=o.slice(-ie),s=[];let r=0;for(let l=t.length-1;l>=0;l--){const k=t[l],v=String(k?.content||""),C=k?.role==="human"?"user":"assistant",I=v.length;if(s.length>=6&&r+I>Ke)break;s.push({role:C,content:v}),r+=I}return s.reverse()}function _t(o,t){const s=String(o||"");return s.length<=t?s:`${s.slice(0,Math.max(0,t-24))}
8
+ ${k}`:R}catch{return s}}function os(o){const t=o.slice(-ie),s=[];let r=0;for(let l=t.length-1;l>=0;l--){const k=t[l],v=String(k?.content||""),C=k?.role==="human"?"user":"assistant",I=v.length;if(s.length>=6&&r+I>Ke)break;s.push({role:C,content:v}),r+=I}return s.reverse()}function xt(o,t){const s=String(o||"");return s.length<=t?s:`${s.slice(0,Math.max(0,t-24))}
9
9
 
10
- [truncated for proxy size]`}function Ht(o){return o.reduce((t,s)=>t+String(s?.content||"").length+64,0)}function ns(o){let t=[...o];if(t.length===0||(t[0]?.role==="system"&&(t[0]={...t[0],content:_t(t[0].content,ce)}),Ht(t)<=ae))return t;const s=t[0],r=t[t.length-1],l=t.slice(1,-1).slice(-4).map(k=>({...k,content:_t(k.content,2500)}));return t=[s,...l,r],Ht(t)<=ae||(t=[{...s,content:_t(s?.content,6e3)},{...r,content:_t(r?.content,8e3)}]),t}function rs(o){const t=[];for(const s of o){const r=$t(s),l=String(r?.description||"").trim();if(!l){t.push(`- ${s}`);continue}t.push(`- ${s}: ${Et(l,80)}`)}return t.length===0?"":`## Active skills (call get_skill_context before first use)
10
+ [truncated for proxy size]`}function Ht(o){return o.reduce((t,s)=>t+String(s?.content||"").length+64,0)}function ns(o){let t=[...o];if(t.length===0||(t[0]?.role==="system"&&(t[0]={...t[0],content:xt(t[0].content,ce)}),Ht(t)<=ae))return t;const s=t[0],r=t[t.length-1],l=t.slice(1,-1).slice(-4).map(k=>({...k,content:xt(k.content,2500)}));return t=[s,...l,r],Ht(t)<=ae||(t=[{...s,content:xt(s?.content,6e3)},{...r,content:xt(r?.content,8e3)}]),t}function rs(o){const t=[];for(const s of o){const r=$t(s),l=String(r?.description||"").trim();if(!l){t.push(`- ${s}`);continue}t.push(`- ${s}: ${Et(l,80)}`)}return t.length===0?"":`## Active skills (call get_skill_context before first use)
11
11
  ${t.join(`
12
12
  `)}`}const pe={cli_plain:["## Response format for this channel","- Output plain terminal text with optional fenced code blocks.","- Use fenced code blocks (```language) when showing code or config. Always include the language tag.","- Outside of code blocks, do NOT use Markdown syntax (no **bold**, __underline__, headings, inline backticks, or markdown tables).","- Keep responses concise and readable in a terminal.","- Write in natural, conversational English. Avoid dumping raw JSON, run IDs, or technical jargon.",'- When reporting test results: summarize in plain language (e.g. "Both tests finished \u2014 the checkbox test passed but the login test failed because..."). Include ticket keys but skip internal run IDs unless the user asks.',"- When something fails, explain the root cause simply and suggest a fix."].join(`
13
13
  `)};function is(o={},t={}){const s=String(t.outputProfile||process.env.ZIBBY_OUTPUT_PROFILE||o.outputProfile||"cli_plain").trim(),r=o?.outputProfiles?.[s];return typeof r=="string"&&r.trim()?r.trim():r&&typeof r.instruction=="string"&&r.instruction.trim()?r.instruction.trim():pe[s]||pe.cli_plain}function Et(o,t){const s=String(o??"");return s.length<=t?s:t<=1?s.slice(0,t):`${s.slice(0,t-1)}\u2026`}function cs(){return!1}function js(o){return o}function as(o){const t=/^```(\w*)\n([\s\S]*?)^```$/gm;return o.replace(t,(s,r,l)=>{const k=l.replace(/\n$/,"");try{const v=r?ne(k,{language:r,ignoreIllegals:!0}):ne(k,{ignoreIllegals:!0}),C=e.gray("\u2500".repeat(Math.min(process.stdout.columns-6||54,72))),I=r?e.dim(` ${r}`):"";return`${C}${I}
14
14
  ${v}
15
- ${C}`}catch{return k}})}function zt(){const o=Number(process.stdout?.columns)||0,t=o>8?Math.max(30,o-4):Ze;return` ${"\u2500".repeat(t)}`}function de(o=[]){const t=Yt.map(r=>({cmd:r.cmd,source:"builtin",name:r.cmd.slice(1),desc:r.desc})),s=o.map(r=>({cmd:`/${r}`,source:"template",name:r,desc:"Command template"}));return[...t,...s]}function ls(o,t){const s=String(o||""),r=Number.isFinite(t)?t:s.length;return!(!s.startsWith("/")||r!==s.length||s.includes(" "))}function us({userName:o,cwd:t,projectName:s,restoredCount:r,skillsLine:l}){const k=Number(process.stdout?.columns)||0,v=Math.max(40,Math.min(k-8,100)),C=Math.max(20,Math.floor((v-3)*.55)),I=v-C-3,U=o||"there",R=s||"No project linked",ht=Ie(t||process.cwd()),W=[`Restored ${r} messages from previous session.`,"",l],rt=["Workspace details","",`v${qe.version} | Hi, ${U}`,`Company: ${R}`,`Directory: ~/${ht}`,`Path: ${t}`,"","Use /help for commands"],E=Math.max(W.length,rt.length),V=(()=>{if(W.length>=E)return W;const F=Math.floor((E-W.length)/2),st=E-W.length-F;return[...Array(F).fill(""),...W,...Array(st).fill("")]})(),H="\u2500",L=` \u250C${H.repeat(C+2)}\u252C${H.repeat(I+2)}\u2510`,et=` \u2514${H.repeat(C+2)}\u2534${H.repeat(I+2)}\u2518`;console.log(e.gray(L));for(let F=0;F<E;F++){const st=Et(V[F]||"",C),it=Et(rt[F]||"",I),yt=" ".repeat(Math.max(0,C-st.length)),u=" ".repeat(Math.max(0,I-it.length)),w=` \u2502 ${st}${yt} \u2502 ${it}${u} \u2502`;console.log(e.gray(w))}console.log(e.gray(et)),console.log("")}function ps(){process.stdout?.isTTY&&(M(process.stdout,0,-2),B(process.stdout,4))}function ds(o){const t=!!(process.stdout?.isTTY&&process.stdin?.isTTY);let s=!1,r=!1,l=!1,k=null,v=0,C=0,I=0;function U(){return e.gray(zt())}function R(){k&&(clearInterval(k),k=null)}function ht(u){!t||!s||!r||!l||(process.stdout.write("\x1B7"),M(process.stdout,0,-2),B(process.stdout,0),G(process.stdout,0),process.stdout.write(` ${u}`),process.stdout.write("\x1B8"))}function W(){if(!(!t||!s)&&C!==0){process.stdout.write("\x1B7"),M(process.stdout,0,2);for(let u=0;u<C;u++)B(process.stdout,0),G(process.stdout,0),u<C-1&&M(process.stdout,0,1);process.stdout.write("\x1B8"),C=0,r&&rt()}}function rt(){!t||!s||!r||(process.stdout.write("\x1B7"),M(process.stdout,0,1),B(process.stdout,0),G(process.stdout,0),process.stdout.write(U()),process.stdout.write("\x1B8"))}function E(u,w){if(!t||!s||!r)return;W();const c=u.slice(0,6);if(c.length!==0){M(process.stdout,0,1);for(let y=0;y<c.length;y++)process.stdout.write(`
16
- `);M(process.stdout,0,-(1+c.length)),process.stdout.write("\x1B7"),M(process.stdout,0,2);for(let y=0;y<c.length;y++){B(process.stdout,0),G(process.stdout,0);const q=y===w?e.cyan("\u203A"):" ",m=y===w?e.white(c[y]):e.gray(c[y]);process.stdout.write(` ${q} /${m}`),y<c.length-1&&M(process.stdout,0,1)}process.stdout.write("\x1B8"),C=c.length,rt()}}function V(){if(!t||!s||!r)return;W();const u=process.stdout.columns||80,w=I>0?Math.ceil(I/u):1;B(process.stdout,0),M(process.stdout,0,-w),l&&M(process.stdout,0,-2),process.stdout.write("\x1B[J"),r=!1}function H(u={}){const w=u.preserveInput===!0;if(!t){o.prompt();return}w||(o.line="",o.cursor=0),I=zt().length;const c=U();process.stdout.write(`${c}
15
+ ${C}`}catch{return k}})}function zt(){const o=Number(process.stdout?.columns)||0,t=o>8?Math.max(30,o-4):Ze;return` ${"\u2500".repeat(t)}`}function de(o=[]){const t=Yt.map(r=>({cmd:r.cmd,source:"builtin",name:r.cmd.slice(1),desc:r.desc})),s=o.map(r=>({cmd:`/${r}`,source:"template",name:r,desc:"Command template"}));return[...t,...s]}function ls(o,t){const s=String(o||""),r=Number.isFinite(t)?t:s.length;return!(!s.startsWith("/")||r!==s.length||s.includes(" "))}function us({userName:o,cwd:t,projectName:s,restoredCount:r,skillsLine:l}){const k=Number(process.stdout?.columns)||0,v=Math.max(40,Math.min(k-8,100)),C=Math.max(20,Math.floor((v-3)*.55)),I=v-C-3,U=o||"there",R=s||"No project linked",ht=Ie(t||process.cwd()),W=[`Restored ${r} messages from previous session.`,"",l],it=["Workspace details","",`v${qe.version} | Hi, ${U}`,`Company: ${R}`,`Directory: ~/${ht}`,`Path: ${t}`,"","Use /help for commands"],E=Math.max(W.length,it.length),X=(()=>{if(W.length>=E)return W;const F=Math.floor((E-W.length)/2),nt=E-W.length-F;return[...Array(F).fill(""),...W,...Array(nt).fill("")]})(),z="\u2500",L=` \u250C${z.repeat(C+2)}\u252C${z.repeat(I+2)}\u2510`,ot=` \u2514${z.repeat(C+2)}\u2534${z.repeat(I+2)}\u2518`;console.log(e.gray(L));for(let F=0;F<E;F++){const nt=Et(X[F]||"",C),ct=Et(it[F]||"",I),yt=" ".repeat(Math.max(0,C-nt.length)),u=" ".repeat(Math.max(0,I-ct.length)),w=` \u2502 ${nt}${yt} \u2502 ${ct}${u} \u2502`;console.log(e.gray(w))}console.log(e.gray(ot)),console.log("")}function ps(){process.stdout?.isTTY&&(M(process.stdout,0,-2),B(process.stdout,4))}function ds(o){const t=!!(process.stdout?.isTTY&&process.stdin?.isTTY);let s=!1,r=!1,l=!1,k=null,v=0,C=0,I=0;function U(){return e.gray(zt())}function R(){k&&(clearInterval(k),k=null)}function ht(u){!t||!s||!r||!l||(process.stdout.write("\x1B7"),M(process.stdout,0,-2),B(process.stdout,0),q(process.stdout,0),process.stdout.write(` ${u}`),process.stdout.write("\x1B8"))}function W(){if(!(!t||!s)&&C!==0){process.stdout.write("\x1B7"),M(process.stdout,0,2);for(let u=0;u<C;u++)B(process.stdout,0),q(process.stdout,0),u<C-1&&M(process.stdout,0,1);process.stdout.write("\x1B8"),C=0,r&&it()}}function it(){!t||!s||!r||(process.stdout.write("\x1B7"),M(process.stdout,0,1),B(process.stdout,0),q(process.stdout,0),process.stdout.write(U()),process.stdout.write("\x1B8"))}function E(u,w){if(!t||!s||!r)return;W();const c=u.slice(0,6);if(c.length!==0){M(process.stdout,0,1);for(let y=0;y<c.length;y++)process.stdout.write(`
16
+ `);M(process.stdout,0,-(1+c.length)),process.stdout.write("\x1B7"),M(process.stdout,0,2);for(let y=0;y<c.length;y++){B(process.stdout,0),q(process.stdout,0);const Z=y===w?e.cyan("\u203A"):" ",m=y===w?e.white(c[y]):e.gray(c[y]);process.stdout.write(` ${Z} /${m}`),y<c.length-1&&M(process.stdout,0,1)}process.stdout.write("\x1B8"),C=c.length,it()}}function X(){if(!t||!s||!r)return;W();const u=process.stdout.columns||80,w=I>0?Math.ceil(I/u):1;B(process.stdout,0),M(process.stdout,0,-w),l&&M(process.stdout,0,-2),process.stdout.write("\x1B[J"),r=!1}function z(u={}){const w=u.preserveInput===!0;if(!t){o.prompt();return}w||(o.line="",o.cursor=0),I=zt().length;const c=U();process.stdout.write(`${c}
17
17
  `),o.prompt(),process.stdout.write(`
18
18
  ${c}
19
- `),ps(),r=!0}function L(){if(!t||!s||!r)return;const u=process.stdout.columns||80,w=I>0?Math.ceil(I/u):1,c=U();process.stdout.write("\x1B7"),M(process.stdout,0,-w);for(let y=0;y<w;y++)B(process.stdout,0),G(process.stdout,0),y<w-1&&M(process.stdout,0,1);B(process.stdout,0),process.stdout.write(c),M(process.stdout,0,2),B(process.stdout,0),G(process.stdout,0),process.stdout.write(c);for(let y=1;y<w;y++)M(process.stdout,0,1),B(process.stdout,0),G(process.stdout,0);process.stdout.write("\x1B8"),I=zt().length}function et(){if(!t||!s||!r)return;const u=(()=>{if(typeof o.getCursorPos!="function")return 0;try{return Math.max(0,Number(o.getCursorPos()?.rows||0))}catch{return 0}})();process.stdout.write("\x1B7"),M(process.stdout,0,-(u+1)),B(process.stdout,0),G(process.stdout,0),process.stdout.write(U()),M(process.stdout,0,u+2),B(process.stdout,0),G(process.stdout,0),process.stdout.write(U()),process.stdout.write("\x1B8")}function F(u){R(),V(),console.log();const w=String(u??"").replace(/\r/g,"").split(`
20
- `);for(;w.length>0&&w[w.length-1]==="";)w.pop();for(const c of w)console.log(c?` ${c}`:"");l=!1}function st(u){const w=String(u??"").replace(/\r/g,"").split(`
19
+ `),ps(),r=!0}function L(){if(!t||!s||!r)return;const u=process.stdout.columns||80,w=I>0?Math.ceil(I/u):1,c=U();process.stdout.write("\x1B7"),M(process.stdout,0,-w);for(let y=0;y<w;y++)B(process.stdout,0),q(process.stdout,0),y<w-1&&M(process.stdout,0,1);B(process.stdout,0),process.stdout.write(c),M(process.stdout,0,2),B(process.stdout,0),q(process.stdout,0),process.stdout.write(c);for(let y=1;y<w;y++)M(process.stdout,0,1),B(process.stdout,0),q(process.stdout,0);process.stdout.write("\x1B8"),I=zt().length}function ot(){if(!t||!s||!r)return;const u=(()=>{if(typeof o.getCursorPos!="function")return 0;try{return Math.max(0,Number(o.getCursorPos()?.rows||0))}catch{return 0}})();process.stdout.write("\x1B7"),M(process.stdout,0,-(u+1)),B(process.stdout,0),q(process.stdout,0),process.stdout.write(U()),M(process.stdout,0,u+2),B(process.stdout,0),q(process.stdout,0),process.stdout.write(U()),process.stdout.write("\x1B8")}function F(u){R(),X(),console.log();const w=String(u??"").replace(/\r/g,"").split(`
20
+ `);for(;w.length>0&&w[w.length-1]==="";)w.pop();for(const c of w)console.log(c?` ${c}`:"");l=!1}function nt(u){const w=String(u??"").replace(/\r/g,"").split(`
21
21
  `);w.length===0&&w.push("");const c=[];for(const y of w)c.push(e.bgGray.white(` ${y||" "} `));return c.join(`
22
- `)}function it(){R();const u=()=>e.gray(`${At[v%At.length]} thinking`);if(!t){console.log(` ${u()}`),l=!0;return}W(),V(),console.log(),console.log(` ${u()}`),H({preserveInput:!0}),l=!0,v+=1,k=setInterval(()=>{l&&(ht(u()),v+=1)},120)}function yt(u){R();const w=String(u??"").replace(/\r/g,"").replace(/⎿/g,"");if(!l){F(w);return}V(),console.log();const c=w.split(`
23
- `);for(;c.length>0&&c[c.length-1]==="";)c.pop();for(const y of c)console.log(y?` ${y}`:"");console.log(),l=!1}return{enabled:t,mount(){if(!s){if(!t){o.prompt(),s=!0;return}s=!0,H()}},refreshPrompt(u={}){if(t&&s){r&&V(),H(u);return}o.prompt()},pushSystem(u){F(u)},pushUser(u){F(st(u))},pushAssistant(u){yt(u)},showAssistantLoading:it,dismissTransientLoading(){R(),l&&t&&s&&r&&(process.stdout.write("\x1B7"),M(process.stdout,0,-2),B(process.stdout,0),G(process.stdout,0),M(process.stdout,0,-1),B(process.stdout,0),G(process.stdout,0),process.stdout.write("\x1B8")),l=!1},touchInputFrame:et,handleResize:L,showCommandDropdown:E,clearCommandDropdown:W}}function fs(){console.log(""),console.log(e.cyan(" Available commands:"));for(const o of Yt)console.log(e.white(` ${o.cmd.padEnd(10)} `)+e.gray(o.desc));console.log(""),console.log(e.cyan(" Chat options:")),console.log(e.white(" --stream, -s ")+e.gray("Enable typewriter effect (default: instant)")),console.log(""),console.log(e.gray(" To install/uninstall skills, just ask naturally:")),console.log(e.gray(' "connect to Jira" \u2022 "add GitHub" \u2022 "remove Slack"')),console.log("")}const ms=Qe;async function Ds(o={}){const t=process.cwd();o.verbose&&(process.env.ZIBBY_VERBOSE="true");const s=o.stream||!1;[lt(t,".env.local"),lt(t,".env")].forEach(c=>{gt(c)&&Me.config({path:c,override:!1})});try{await import("@zibby/skills")}catch{}function l(){const c=Wt();if(!c)return!1;try{const y=JSON.parse(atob(c.split(".")[1]));return y.exp&&y.exp*1e3>Date.now()}catch{return!1}}if(!l()){Ue();const c=re(),{spawn:y}=await import("child_process"),q=await fetch(`${c}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});q.ok||(console.log(e.red("\n Could not start login. Try `zibby login`.\n")),process.exit(1));const{deviceCode:m,verificationUrl:n,expiresIn:O,interval:ut}=await q.json(),ot=process.platform;y(ot==="darwin"?"open":ot==="win32"?"cmd":"xdg-open",ot==="win32"?["/c","start","",n]:[n],{detached:!0,stdio:"ignore"}).unref(),console.log(e.cyan(`
22
+ `)}function ct(){R();const u=()=>e.gray(`${At[v%At.length]} thinking`);if(!t){console.log(` ${u()}`),l=!0;return}W(),X(),console.log(),console.log(` ${u()}`),z({preserveInput:!0}),l=!0,v+=1,k=setInterval(()=>{l&&(ht(u()),v+=1)},120)}function yt(u){R();const w=String(u??"").replace(/\r/g,"").replace(/⎿/g,"");if(!l){F(w);return}X(),console.log();const c=w.split(`
23
+ `);for(;c.length>0&&c[c.length-1]==="";)c.pop();for(const y of c)console.log(y?` ${y}`:"");console.log(),l=!1}return{enabled:t,mount(){if(!s){if(!t){o.prompt(),s=!0;return}s=!0,z()}},refreshPrompt(u={}){if(t&&s){r&&X(),z(u);return}o.prompt()},pushSystem(u){F(u)},pushUser(u){F(nt(u))},pushAssistant(u){yt(u)},showAssistantLoading:ct,dismissTransientLoading(){R(),l&&t&&s&&r&&(process.stdout.write("\x1B7"),M(process.stdout,0,-2),B(process.stdout,0),q(process.stdout,0),M(process.stdout,0,-1),B(process.stdout,0),q(process.stdout,0),process.stdout.write("\x1B8")),l=!1},touchInputFrame:ot,handleResize:L,showCommandDropdown:E,clearCommandDropdown:W}}function fs(){console.log(""),console.log(e.cyan(" Available commands:"));for(const o of Yt)console.log(e.white(` ${o.cmd.padEnd(10)} `)+e.gray(o.desc));console.log(""),console.log(e.cyan(" Chat options:")),console.log(e.white(" --stream, -s ")+e.gray("Enable typewriter effect (default: instant)")),console.log(""),console.log(e.gray(" To install/uninstall skills, just ask naturally:")),console.log(e.gray(' "connect to Jira" \u2022 "add GitHub" \u2022 "remove Slack"')),console.log("")}const ms=Qe;async function Ds(o={}){const t=process.cwd();o.verbose&&(process.env.ZIBBY_VERBOSE="true");const s=o.stream||!1;[ut(t,".env.local"),ut(t,".env")].forEach(c=>{gt(c)&&Me.config({path:c,override:!1})});try{await import("@zibby/skills")}catch{}function l(){const c=Wt();if(!c)return!1;try{const y=JSON.parse(atob(c.split(".")[1]));return y.exp&&y.exp*1e3>Date.now()}catch{return!1}}if(!l()){Ue();const c=re(),{spawn:y}=await import("child_process"),Z=await fetch(`${c}/cli/login/initiate`,{method:"POST",headers:{"Content-Type":"application/json"}});Z.ok||(console.log(e.red("\n Could not start login. Try `zibby login`.\n")),process.exit(1));const{deviceCode:m,verificationUrl:n,expiresIn:O,interval:Q}=await Z.json(),Y=process.platform;y(Y==="darwin"?"open":Y==="win32"?"cmd":"xdg-open",Y==="win32"?["/c","start","",n]:[n],{detached:!0,stdio:"ignore"}).unref(),console.log(e.cyan(`
24
24
  Opening browser to authorize Zibby CLI...`)),console.log(e.gray(` ${n}
25
- `));const ct=le();ct.setLabel("waiting for authorization");const pt=(ut||3)*1e3,dt=Math.floor(O/(ut||3));let X=!1;for(let nt=0;nt<dt;nt++){await Ve(pt);try{const Q=await fetch(`${c}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:m})});if(Q.status===202)continue;if(!Q.ok)break;const z=await Q.json();if(z.status==="authorized"){Be(z.token),Re(z.user),z.proxyUrl&&Fe(z.proxyUrl),z.mem0ProxyUrl&&We(z.mem0ProxyUrl),X=!0;break}if(z.status==="denied")break}catch{break}}ct(),X||(console.log(e.red("\n Login failed or timed out. Run `zibby login` to try again.\n")),process.exit(1))}const k=await ts(t),v=await es(t),C=o.agent||"assistant",I=Wt();I&&!process.env.ZIBBY_USER_TOKEN&&(process.env.ZIBBY_USER_TOKEN=I);const U=De()||je();U&&!process.env.ZIBBY_MEM0_OPENAI_BASE_URL&&(process.env.ZIBBY_MEM0_OPENAI_BASE_URL=U),process.env.AGENT_TYPE=C,process.env.ZIBBY_CHAT_OWNER_PID=String(process.pid);try{const{cleanupStalePidFiles:c}=await import("../utils/chat-run-lifecycle.js");c(t,k)}catch{}let R;try{R=ve({state:{agentType:C}})}catch(c){console.log(e.red(`
25
+ `));const at=le();at.setLabel("waiting for authorization");const pt=(Q||3)*1e3,dt=Math.floor(O/(Q||3));let tt=!1;for(let rt=0;rt<dt;rt++){await Ve(pt);try{const et=await fetch(`${c}/cli/login/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:m})});if(et.status===202)continue;if(!et.ok)break;const J=await et.json();if(J.status==="authorized"){Be(J.token),Re(J.user),J.proxyUrl&&Fe(J.proxyUrl),J.mem0ProxyUrl&&We(J.mem0ProxyUrl),tt=!0;break}if(J.status==="denied")break}catch{break}}at(),tt||(console.log(e.red("\n Login failed or timed out. Run `zibby login` to try again.\n")),process.exit(1))}const k=await ts(t),v=await es(t),C=o.agent||"assistant",I=Wt();I&&!process.env.ZIBBY_USER_TOKEN&&(process.env.ZIBBY_USER_TOKEN=I);const U=De()||je();U&&!process.env.ZIBBY_MEM0_OPENAI_BASE_URL&&(process.env.ZIBBY_MEM0_OPENAI_BASE_URL=U),process.env.AGENT_TYPE=C,process.env.ZIBBY_CHAT_OWNER_PID=String(process.pid);try{const{cleanupStalePidFiles:c}=await import("../utils/chat-run-lifecycle.js");c(t,k)}catch{}let R;try{R=ve({state:{agentType:C}})}catch(c){console.log(e.red(`
26
26
  ${c.message}
27
- `)),process.exit(1)}const ht=Ne(),rt=Oe()?.[0]?.name,E=He(t),V=v.skills||[],H=Ye(t),L=H?[...new Set([...V,...H])]:[...V];let et={data:null,timestamp:0};const F=300*1e3,st={jira:"jira",github:"github",slack:"slack",sentry:"sentry"};try{const c=Wt();if(c){const y=re(),q=await fetch(`${y}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${c}`}});if(q.ok){const m=await q.json();for(const[n,O]of Object.entries(st))m[n]?.connected&&!L.includes(O)&&$t(O)&&L.push(O);It(t,L)}}}catch{}const it=L.filter(c=>c!=="skill-installer"&&c!=="core-tools"),yt=it.length>0?`Skills: ${it.join(", ")}`:"Skills: (none)";us({userName:ht?.name?.split(" ")[0],cwd:t,projectName:rt,restoredCount:E.length,skillsLine:yt});let u=ue(t),w=de(u);return new Promise(c=>{const y=process.env.ZIBBY_CHAT_TAB_COMPLETION==="1",q={input:process.stdin,output:process.stdout,prompt:e.green(" > "),terminal:!0};y&&(q.completer=p=>{const i=String(p||"");if(!i.startsWith("/"))return[[],i];const g=w.map(P=>P.cmd),$=g.filter(P=>P.startsWith(i));return[$.length>0?$:g,i]});const m=Pe(q),n=ds(m);let O=null,ut=!1;const ot=[],fe=0,me=1200;let ct=!1,pt=!1,dt=!1,X=!1,nt="",Q=0;const z=typeof m._ttyWrite=="function"?m._ttyWrite.bind(m):null;z&&(m._ttyWrite=(...p)=>{if(!(X||Date.now()<Q))return z(...p)});function ge(){dt||!process.stdout?.isTTY||typeof process.stdout.write!="function"||(process.stdout.write("\x1B[?2004h"),dt=!0)}function Jt(){dt&&(!process.stdout?.isTTY||typeof process.stdout.write!="function"||(process.stdout.write("\x1B[?2004l"),dt=!1))}function he(p){const i="\x1B[200~",g="\x1B[201~";if(!X&&!p.includes(i))return!1;let $=p,P=!1;for(;$.length>0;){if(!X){const A=$.indexOf(i);if(A===-1)break;P=!0,Kt(),X=!0,nt="",$=$.slice(A+i.length);continue}const J=$.indexOf(g);if(J===-1){P=!0,nt+=$;break}P=!0,nt+=$.slice(0,J);const tt=String(nt||"").replace(/\r\n/g,`
27
+ `)),process.exit(1)}const ht=Ne(),it=Oe()?.[0]?.name,E=He(t),X=v.skills||[],z=Ye(t),L=z?[...new Set([...X,...z])]:[...X];let ot={data:null,timestamp:0};const F=300*1e3,nt={jira:"jira",github:"github",slack:"slack",sentry:"sentry"};try{const c=Wt();if(c){const y=re(),Z=await fetch(`${y}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${c}`}});if(Z.ok){const m=await Z.json();for(const[n,O]of Object.entries(nt)){const Q=m[n]?.connected,Y=L.indexOf(O);Q&&Y===-1&&$t(O)?L.push(O):!Q&&Y!==-1&&L.splice(Y,1)}It(t,L)}}}catch{}const ct=L.filter(c=>c!=="skill-installer"&&c!=="core-tools"),yt=ct.length>0?`Skills: ${ct.join(", ")}`:"Skills: (none)";us({userName:ht?.name?.split(" ")[0],cwd:t,projectName:it,restoredCount:E.length,skillsLine:yt});let u=ue(t),w=de(u);return new Promise(c=>{const y=process.env.ZIBBY_CHAT_TAB_COMPLETION==="1",Z={input:process.stdin,output:process.stdout,prompt:e.green(" > "),terminal:!0};y&&(Z.completer=p=>{const i=String(p||"");if(!i.startsWith("/"))return[[],i];const g=w.map(P=>P.cmd),$=g.filter(P=>P.startsWith(i));return[$.length>0?$:g,i]});const m=Pe(Z),n=ds(m);let O=null,Q=!1;const Y=[],fe=0,me=1200;let at=!1,pt=!1,dt=!1,tt=!1,rt="",et=0;const J=typeof m._ttyWrite=="function"?m._ttyWrite.bind(m):null;J&&(m._ttyWrite=(...p)=>{if(!(tt||Date.now()<et))return J(...p)});function ge(){dt||!process.stdout?.isTTY||typeof process.stdout.write!="function"||(process.stdout.write("\x1B[?2004h"),dt=!0)}function Jt(){dt&&(!process.stdout?.isTTY||typeof process.stdout.write!="function"||(process.stdout.write("\x1B[?2004l"),dt=!1))}function he(p){const i="\x1B[200~",g="\x1B[201~";if(!tt&&!p.includes(i))return!1;let $=p,P=!1;for(;$.length>0;){if(!tt){const A=$.indexOf(i);if(A===-1)break;P=!0,Kt(),tt=!0,rt="",$=$.slice(A+i.length);continue}const G=$.indexOf(g);if(G===-1){P=!0,rt+=$;break}P=!0,rt+=$.slice(0,G);const st=String(rt||"").replace(/\r\n/g,`
28
28
  `).replace(/\r/g,`
29
- `);if(tt.length>0){const A=tt.split(`
30
- `);for(const Z of A)Rt(Z)}vt(),nt="",X=!1,$=$.slice(J+g.length)}return P}function Gt(){if(!ct){ct=!0;try{Pt(t,E),It(t,L)}catch{}try{Jt()}catch{}try{m.close()}catch{}process.exit(0)}}async function Lt(){if(!ct){ct=!0,typeof R?.cleanup=="function"&&await R.cleanup().catch(()=>{});try{const{killAllChatOrchestratedRuns:p}=await import("../utils/chat-run-lifecycle.js"),{postCliInterruptedRunIndex:i}=await import("@zibby/core/utils/run-index-post-cli.js");p(t,process.pid,k),i({cwd:t,config:k})}catch{}Pt(t,E),It(t,L),n.pushSystem(e.gray("Session saved. Goodbye!")),Jt(),m.close(),process.exit(0)}}if(n.mount(),ge(),process.stdout?.isTTY){let p;process.stdout.on("resize",()=>{clearTimeout(p),p=setTimeout(()=>{n.handleResize()},80)})}let Mt=0;const xt=p=>{if(typeof p=="string"?p==="\x1B":p&&typeof p.length=="number"?p.length===1&&p[0]===27:!1){O&&O.abort(),Gt();return}const g=typeof p=="string"?p:p&&typeof p.length=="number"?Buffer.from(p).toString("utf8"):"";if(!g)return;if(he(g)){Mt=Date.now()+1200,Q=Date.now()+1200,Bt();return}const $=(g.includes(`
29
+ `);if(st.length>0){const A=st.split(`
30
+ `);for(const K of A)Rt(K)}vt(),rt="",tt=!1,$=$.slice(G+g.length)}return P}function Gt(){if(!at){at=!0;try{Pt(t,E),It(t,L)}catch{}try{Jt()}catch{}try{m.close()}catch{}process.exit(0)}}async function Lt(){if(!at){at=!0,typeof R?.cleanup=="function"&&await R.cleanup().catch(()=>{});try{const{killAllChatOrchestratedRuns:p}=await import("../utils/chat-run-lifecycle.js"),{postCliInterruptedRunIndex:i}=await import("@zibby/core/utils/run-index-post-cli.js");p(t,process.pid,k),i({cwd:t,config:k})}catch{}Pt(t,E),It(t,L),n.pushSystem(e.gray("Session saved. Goodbye!")),Jt(),m.close(),process.exit(0)}}if(n.mount(),ge(),process.stdout?.isTTY){let p;process.stdout.on("resize",()=>{clearTimeout(p),p=setTimeout(()=>{n.handleResize()},80)})}let Mt=0;const _t=p=>{if(typeof p=="string"?p==="\x1B":p&&typeof p.length=="number"?p.length===1&&p[0]===27:!1){O&&O.abort(),Gt();return}const g=typeof p=="string"?p:p&&typeof p.length=="number"?Buffer.from(p).toString("utf8"):"";if(!g)return;if(he(g)){Mt=Date.now()+1200,et=Date.now()+1200,Bt();return}const $=(g.includes(`
31
31
  `)||g.includes("\r"))&&g!=="\r"&&g!==`
32
32
  `&&g!==`\r
33
- `,P=g.includes("\x1B[200~")||g.includes("\x1B[201~"),J=g.length>=16&&/\s/.test(g)&&!g.startsWith("\x1B");($||P||J)&&(Mt=Date.now()+1200,Q=Date.now()+1200,Kt(),Bt())},N={query:"",matches:[],selected:0},Y={prefix:"",matches:[],nextIndex:0},x={active:!1,prefix:"",lines:[],timer:null},Nt=[];let qt=0,Ot="";const ye=new Set(Yt.map(p=>p.cmd));function ft(p,{preserveFrame:i=!1}={}){const g=String(p||"");m.line=g,m.cursor=g.length,Ot=g,typeof m._refreshLine=="function"?m._refreshLine():m.prompt(),i&&n.touchInputFrame()}function Zt(){Y.prefix="",Y.matches=[],Y.nextIndex=0}function vt(){if(x.timer&&(clearTimeout(x.timer),x.timer=null),x.active&&x.lines.length>0){qt+=1;const p=x.lines.length,i=`[Pasted text #${qt} +${p} lines]`,g=x.lines.join(`
34
- `);Nt.push({placeholder:i,text:g});const $=String(x.prefix||"").trimEnd(),P=$?`${$} ${i}`:i;ft(P,{preserveFrame:!0}),mt(m.line)}x.active=!1,x.prefix="",x.lines=[],Q=0}function Bt(){x.timer&&clearTimeout(x.timer),x.timer=setTimeout(()=>{vt()},180)}function Kt(){x.active||(x.active=!0,x.prefix=String(Ot||m.line||""),x.lines=[],ft(x.prefix,{preserveFrame:!0}))}function Rt(p){return x.active?(x.lines.push(String(p||"")),ft(x.prefix,{preserveFrame:!0}),Bt(),!0):!1}function we(p){let i=String(p||"");for(const g of Nt)i=i.split(g.placeholder).join(g.text);return i}function mt(p){const i=String(p||"");if(!i.startsWith("/")||i.includes(" ")||i.length===0){N.query="",N.matches=[],N.selected=0,n.clearCommandDropdown();return}u=ue(t),w=de(u);const g=i.slice(1).toLowerCase(),$=u.filter(P=>P.toLowerCase().startsWith(g));N.query=g,N.matches=$,N.selected=Math.min(N.selected,Math.max(0,$.length-1)),n.showCommandDropdown($,N.selected)}const Ut=(p,i)=>{if(i?.name==="escape"||i?.sequence==="\x1B"){O&&O.abort(),Gt();return}if((i?.name==="return"||i?.name==="enter")&&(pt=!0),(i?.name==="backspace"||i?.name==="delete")&&n.touchInputFrame(),i?.name==="tab"&&!i?.shift){const P=String(m.line||""),J=Number(m.cursor||P.length);if(!ls(P,J)){Zt(),mt(m.line);return}const tt=P.slice(1).toLowerCase();if(Y.prefix!==tt&&(Y.prefix=tt,Y.matches=w.map(Z=>Z.cmd).filter(Z=>Z.toLowerCase().startsWith(`/${tt}`)),Y.nextIndex=0),Y.matches.length===0)return;const A=Y.nextIndex%Y.matches.length;Y.nextIndex+=1,ft(Y.matches[A]),mt(m.line);return}const g=String(m.line||""),$=g.startsWith("/")&&!g.includes(" ")&&N.matches.length>0;if(i?.name==="up"||i?.name==="down"){if(!$){mt(m.line);return}const P=i.name==="up"?-1:1,J=N.matches.length;N.selected=(N.selected+P+J)%J;const tt=N.matches[N.selected];ft(`/${tt}`,{preserveFrame:!0}),n.showCommandDropdown(N.matches,N.selected);return}i?.name!=="tab"&&Zt(),setTimeout(()=>{mt(m.line),x.active||(Ot=String(m.line||""))},50)};process.stdin?.on&&(Ae(process.stdin,m),process.stdin.on("keypress",Ut)),n.enabled&&process.stdin?.on&&(typeof process.stdin.prependListener=="function"?process.stdin.prependListener("data",xt):process.stdin.on("data",xt)),m.on("line",async p=>{try{let i=String(p||"");const g=pt;if(pt=!1,!g&&(x.active||X||Date.now()<Mt||Date.now()<Q)){if(x.active&&i.length>0){Rt(i);return}x.active&&(vt(),n.refreshPrompt());return}if(x.active&&(vt(),i=String(m.line||i||"")),Rt(i))return;const $=i.trim(),P=N.matches[N.selected];if($.startsWith("/")&&!$.includes(" ")&&N.matches.length>0&&!ye.has($)&&$!==`/${P}`){n.clearCommandDropdown(),n.refreshPrompt(),ft(`/${P}`),mt(`/${P}`);return}n.clearCommandDropdown();const A=String(i||"").replace(/[\u0000-\u001F\u007F-\u009F]/g,"").trim();if(!A){n.enabled&&process.stdout?.isTTY&&(M(process.stdout,0,-1),B(process.stdout,4));return}if(ut&&A!=="/exit"&&A!=="/quit"){O&&O.abort(),ot.push(A),n.pushSystem(e.gray("Processing your message...")),n.refreshPrompt({preserveInput:!0});return}const Z=1e4;if(A.length>Z){n.pushSystem(e.red(`\u26A0 Input too long (${A.length} chars). Maximum: ${Z} characters.`)),n.pushSystem(e.gray("Tip: If you need to share logs, use a file instead:")),n.pushSystem(e.gray(" 1. Save to file: pbpaste > debug.log")),n.pushSystem(e.gray(' 2. Ask: "analyze debug.log in current directory"')),n.refreshPrompt();return}if(A==="/exit"||A==="/quit"){Lt();return}if(A==="/help"){fs(),n.refreshPrompt();return}if(A==="/skills"){const _=$t("skill-installer")?.catalog||{},h=L.filter(b=>b!=="skill-installer");console.log(e.cyan(`
35
- Active skills:`)),h.length===0&&console.log(e.gray(" (none)"));for(const b of h){const S=_[b]||{};console.log(e.green(` \u2713 ${b}`)+e.gray(S.description?` \u2014 ${S.description}`:""))}const T=Object.keys(_).filter(b=>!L.includes(b));if(T.length>0){console.log(e.cyan(`
36
- Available:`));for(const b of T){const S=_[b],f=S.envKeys?.length>0?ms(S.envKeys).ok?e.green(" \u2713 configured"):e.yellow(` \u26A0 needs: ${S.envKeys.join(", ")}`):"";console.log(e.white(` - ${b}`)+e.gray(` \u2014 ${S.description}`)+f)}}console.log(e.gray(`
33
+ `,P=g.includes("\x1B[200~")||g.includes("\x1B[201~"),G=g.length>=16&&/\s/.test(g)&&!g.startsWith("\x1B");($||P||G)&&(Mt=Date.now()+1200,et=Date.now()+1200,Kt(),Bt())},N={query:"",matches:[],selected:0},H={prefix:"",matches:[],nextIndex:0},_={active:!1,prefix:"",lines:[],timer:null},Nt=[];let qt=0,Ot="";const ye=new Set(Yt.map(p=>p.cmd));function ft(p,{preserveFrame:i=!1}={}){const g=String(p||"");m.line=g,m.cursor=g.length,Ot=g,typeof m._refreshLine=="function"?m._refreshLine():m.prompt(),i&&n.touchInputFrame()}function Zt(){H.prefix="",H.matches=[],H.nextIndex=0}function vt(){if(_.timer&&(clearTimeout(_.timer),_.timer=null),_.active&&_.lines.length>0){qt+=1;const p=_.lines.length,i=`[Pasted text #${qt} +${p} lines]`,g=_.lines.join(`
34
+ `);Nt.push({placeholder:i,text:g});const $=String(_.prefix||"").trimEnd(),P=$?`${$} ${i}`:i;ft(P,{preserveFrame:!0}),mt(m.line)}_.active=!1,_.prefix="",_.lines=[],et=0}function Bt(){_.timer&&clearTimeout(_.timer),_.timer=setTimeout(()=>{vt()},180)}function Kt(){_.active||(_.active=!0,_.prefix=String(Ot||m.line||""),_.lines=[],ft(_.prefix,{preserveFrame:!0}))}function Rt(p){return _.active?(_.lines.push(String(p||"")),ft(_.prefix,{preserveFrame:!0}),Bt(),!0):!1}function we(p){let i=String(p||"");for(const g of Nt)i=i.split(g.placeholder).join(g.text);return i}function mt(p){const i=String(p||"");if(!i.startsWith("/")||i.includes(" ")||i.length===0){N.query="",N.matches=[],N.selected=0,n.clearCommandDropdown();return}u=ue(t),w=de(u);const g=i.slice(1).toLowerCase(),$=u.filter(P=>P.toLowerCase().startsWith(g));N.query=g,N.matches=$,N.selected=Math.min(N.selected,Math.max(0,$.length-1)),n.showCommandDropdown($,N.selected)}const Ut=(p,i)=>{if(i?.name==="escape"||i?.sequence==="\x1B"){O&&O.abort(),Gt();return}if((i?.name==="return"||i?.name==="enter")&&(pt=!0),(i?.name==="backspace"||i?.name==="delete")&&n.touchInputFrame(),i?.name==="tab"&&!i?.shift){const P=String(m.line||""),G=Number(m.cursor||P.length);if(!ls(P,G)){Zt(),mt(m.line);return}const st=P.slice(1).toLowerCase();if(H.prefix!==st&&(H.prefix=st,H.matches=w.map(K=>K.cmd).filter(K=>K.toLowerCase().startsWith(`/${st}`)),H.nextIndex=0),H.matches.length===0)return;const A=H.nextIndex%H.matches.length;H.nextIndex+=1,ft(H.matches[A]),mt(m.line);return}const g=String(m.line||""),$=g.startsWith("/")&&!g.includes(" ")&&N.matches.length>0;if(i?.name==="up"||i?.name==="down"){if(!$){mt(m.line);return}const P=i.name==="up"?-1:1,G=N.matches.length;N.selected=(N.selected+P+G)%G;const st=N.matches[N.selected];ft(`/${st}`,{preserveFrame:!0}),n.showCommandDropdown(N.matches,N.selected);return}i?.name!=="tab"&&Zt(),setTimeout(()=>{mt(m.line),_.active||(Ot=String(m.line||""))},50)};process.stdin?.on&&(Ae(process.stdin,m),process.stdin.on("keypress",Ut)),n.enabled&&process.stdin?.on&&(typeof process.stdin.prependListener=="function"?process.stdin.prependListener("data",_t):process.stdin.on("data",_t)),m.on("line",async p=>{try{let i=String(p||"");const g=pt;if(pt=!1,!g&&(_.active||tt||Date.now()<Mt||Date.now()<et)){if(_.active&&i.length>0){Rt(i);return}_.active&&(vt(),n.refreshPrompt());return}if(_.active&&(vt(),i=String(m.line||i||"")),Rt(i))return;const $=i.trim(),P=N.matches[N.selected];if($.startsWith("/")&&!$.includes(" ")&&N.matches.length>0&&!ye.has($)&&$!==`/${P}`){n.clearCommandDropdown(),n.refreshPrompt(),ft(`/${P}`),mt(`/${P}`);return}n.clearCommandDropdown();const A=String(i||"").replace(/[\u0000-\u001F\u007F-\u009F]/g,"").trim();if(!A){n.enabled&&process.stdout?.isTTY&&(M(process.stdout,0,-1),B(process.stdout,4));return}if(Q&&A!=="/exit"&&A!=="/quit"){O&&O.abort(),Y.push(A),n.pushSystem(e.gray("Processing your message...")),n.refreshPrompt({preserveInput:!0});return}const K=1e4;if(A.length>K){n.pushSystem(e.red(`\u26A0 Input too long (${A.length} chars). Maximum: ${K} characters.`)),n.pushSystem(e.gray("Tip: If you need to share logs, use a file instead:")),n.pushSystem(e.gray(" 1. Save to file: pbpaste > debug.log")),n.pushSystem(e.gray(' 2. Ask: "analyze debug.log in current directory"')),n.refreshPrompt();return}if(A==="/exit"||A==="/quit"){Lt();return}if(A==="/help"){fs(),n.refreshPrompt();return}if(A==="/skills"){const x=$t("skill-installer")?.catalog||{},h=L.filter(b=>b!=="skill-installer");console.log(e.cyan(`
35
+ Active skills:`)),h.length===0&&console.log(e.gray(" (none)"));for(const b of h){const S=x[b]||{};console.log(e.green(` \u2713 ${b}`)+e.gray(S.description?` \u2014 ${S.description}`:""))}const T=Object.keys(x).filter(b=>!L.includes(b));if(T.length>0){console.log(e.cyan(`
36
+ Available:`));for(const b of T){const S=x[b],f=S.envKeys?.length>0?ms(S.envKeys).ok?e.green(" \u2713 configured"):e.yellow(` \u26A0 needs: ${S.envKeys.join(", ")}`):"";console.log(e.white(` - ${b}`)+e.gray(` \u2014 ${S.description}`)+f)}}console.log(e.gray(`
37
37
  Just ask to install: "connect to Jira", "add GitHub", etc.
38
38
  `)),n.refreshPrompt();return}if(A.startsWith("/history")){if(E.length===0)console.log(e.gray(`
39
39
  No conversation history.
40
- `));else{const a=A.split(/\s+/).slice(1),_=a.includes("--all"),h=a.indexOf("-n"),T=h>=0&&a[h+1]?parseInt(a[h+1],10):NaN,b=_?E.length:isNaN(T)?10:T,S=E.slice(-b);console.log(e.gray(`
41
- Showing ${S.length} of ${E.length} messages${_?" (all)":""}:
42
- `));for(const f of S){const d=f.role==="human"?e.green(" You"):e.cyan(" Zibby"),j=_||T>10?500:100,D=f.content.length>j?`${f.content.substring(0,j)}...`:f.content;console.log(`${d}: ${e.white(D)}`)}console.log("")}n.refreshPrompt();return}if(A==="/clear"){E.length=0,Pt(t,E),console.log(e.gray(`
40
+ `));else{const a=A.split(/\s+/).slice(1),x=a.includes("--all"),h=a.indexOf("-n"),T=h>=0&&a[h+1]?parseInt(a[h+1],10):NaN,b=x?E.length:isNaN(T)?10:T,S=E.slice(-b);console.log(e.gray(`
41
+ Showing ${S.length} of ${E.length} messages${x?" (all)":""}:
42
+ `));for(const f of S){const d=f.role==="human"?e.green(" You"):e.cyan(" Zibby"),j=x||T>10?500:100,D=f.content.length>j?`${f.content.substring(0,j)}...`:f.content;console.log(`${d}: ${e.white(D)}`)}console.log("")}n.refreshPrompt();return}if(A==="/clear"){E.length=0,Pt(t,E),console.log(e.gray(`
43
43
  History cleared.
44
44
  `)),n.refreshPrompt();return}if(A.startsWith("/memory")){const a=L.includes("chat-memory")?$t("chat-memory"):null;if(!a?.handleToolCall){console.log(e.yellow(`
45
45
  Chat memory not active. Install with: "add chat memory"
46
- `)),n.refreshPrompt();return}const _=A.split(/\s+/).slice(1),h=_[0]||"brief",T={options:{workspace:t}};try{if(h==="facts"||h==="all"){const b=parseInt(_[1],10)||30,S=await a.handleToolCall("memory_recall",{limit:b},T),f=JSON.parse(S);if(console.log(e.cyan(`
46
+ `)),n.refreshPrompt();return}const x=A.split(/\s+/).slice(1),h=x[0]||"brief",T={options:{workspace:t}};try{if(h==="facts"||h==="all"){const b=parseInt(x[1],10)||30,S=await a.handleToolCall("memory_recall",{limit:b},T),f=JSON.parse(S);if(console.log(e.cyan(`
47
47
  Stored memories (${f.total}):
48
48
  `)),f.total===0)console.log(e.gray(` (empty \u2014 memories are saved as the agent learns things)
49
- `));else{for(const d of f.memories){const j=e.yellow(`[${d.category}]`),D=Number(d.relevance)<1?e.gray(` (${(Number(d.relevance)*100).toFixed(0)}%)`):"",St=d.ticket_key?e.magenta(` ${d.ticket_key}`):"",kt=d.source?e.gray(` via ${d.source}`):"";console.log(` ${j}${St} ${e.white(d.content)}${D}${kt}`)}console.log("")}}else if(h==="tasks"){const b=parseInt(_[1],10)||20,S=await a.handleToolCall("task_history",{limit:b},T),f=JSON.parse(S);if(console.log(e.cyan(`
49
+ `));else{for(const d of f.memories){const j=e.yellow(`[${d.category}]`),D=Number(d.relevance)<1?e.gray(` (${(Number(d.relevance)*100).toFixed(0)}%)`):"",St=d.ticket_key?e.magenta(` ${d.ticket_key}`):"",kt=d.source?e.gray(` via ${d.source}`):"";console.log(` ${j}${St} ${e.white(d.content)}${D}${kt}`)}console.log("")}}else if(h==="tasks"){const b=parseInt(x[1],10)||20,S=await a.handleToolCall("task_history",{limit:b},T),f=JSON.parse(S);if(console.log(e.cyan(`
50
50
  Task history (${f.total}):
51
51
  `)),f.total===0)console.log(e.gray(` (no tasks logged yet)
52
52
  `));else{for(const d of f.tasks){const j=d.status==="passed"?e.green("\u2713"):d.status==="failed"?e.red("\u2717"):e.yellow("\u25CB"),D=d.ticket_key?e.magenta(` ${d.ticket_key}`):"",St=e.gray(`[${d.type}]`),kt=d.result_summary?e.gray(` \u2014 ${d.result_summary.slice(0,80)}`):"";console.log(` ${j} ${St}${D} ${e.white(d.title)}${kt}`)}console.log("")}}else if(h==="sessions"){const b=await a.handleToolCall("memory_brief",{},T),S=JSON.parse(b);if(console.log(e.cyan(`
53
53
  Recent sessions (${S.recentSessions?.length||0}):
54
54
  `)),!S.recentSessions?.length)console.log(e.gray(` (no sessions saved yet)
55
- `));else{for(const f of S.recentSessions){const d=f.tickets?e.magenta(` [${f.tickets}]`):"",j=f.tasks_run>0?e.gray(` \u2014 ${f.tasks_run} tasks (${f.tasks_passed} passed, ${f.tasks_failed} failed)`):"",D=f.created_at?e.gray(` ${f.created_at.split("T")[0]}`):"";if(console.log(` ${e.white(f.summary)}${d}${j}${D}`),f.key_facts)for(const St of f.key_facts.split(";").map(kt=>kt.trim()).filter(Boolean))console.log(e.gray(` \u2192 ${St}`))}console.log("")}}else if(h==="search"){const b=_.slice(1).join(" ");if(!b)console.log(e.yellow(`
55
+ `));else{for(const f of S.recentSessions){const d=f.tickets?e.magenta(` [${f.tickets}]`):"",j=f.tasks_run>0?e.gray(` \u2014 ${f.tasks_run} tasks (${f.tasks_passed} passed, ${f.tasks_failed} failed)`):"",D=f.created_at?e.gray(` ${f.created_at.split("T")[0]}`):"";if(console.log(` ${e.white(f.summary)}${d}${j}${D}`),f.key_facts)for(const St of f.key_facts.split(";").map(kt=>kt.trim()).filter(Boolean))console.log(e.gray(` \u2192 ${St}`))}console.log("")}}else if(h==="search"){const b=x.slice(1).join(" ");if(!b)console.log(e.yellow(`
56
56
  Usage: /memory search <keyword>
57
57
  `));else{const S=await a.handleToolCall("memory_recall",{query:b,limit:20},T),f=JSON.parse(S);console.log(e.cyan(`
58
58
  Search "${b}" \u2014 ${f.total} results:
@@ -61,22 +61,22 @@ ${c}
61
61
  `)),console.log(e.white(` Facts stored: ${f>0?e.cyan(f):e.gray("0")}`)),console.log(e.white(` Sessions saved: ${d>0?e.cyan(d):e.gray("0")}`)),j&&console.log(e.white(` Task history: ${e.gray(j)}`)),console.log(e.gray(`
62
62
  Subcommands:`)),console.log(e.gray(" /memory facts [n] \u2014 List all stored memories")),console.log(e.gray(" /memory tasks [n] \u2014 List task history")),console.log(e.gray(" /memory sessions \u2014 List session summaries")),console.log(e.gray(" /memory search <keyword> \u2014 Search memories")),console.log("")}}catch(b){console.log(e.red(`
63
63
  Memory error: ${b.message}
64
- `))}n.refreshPrompt();return}n.enabled&&process.stdout?.isTTY&&(M(process.stdout,0,-1),B(process.stdout,0)),n.pushUser(A),n.refreshPrompt(),n.showAssistantLoading();const Vt=we(A),Tt=ss(t,Vt);if(Nt.length=0,!String(Tt||"").trim()){n.dismissTransientLoading(),n.refreshPrompt();return}if(Tt.length>Z){n.pushAssistant(e.red(`Input too long after command expansion (${Tt.length} chars).`)),n.pushSystem(e.gray(`Try shortening the command template or user text. Limit: ${Z} chars.`)),n.refreshPrompt();return}ut=!0;let K=v.systemPrompt||"You are Zibby, a helpful AI assistant.";const Xt=is(v,o);Xt&&(K+=`
64
+ `))}n.refreshPrompt();return}n.enabled&&process.stdout?.isTTY&&(M(process.stdout,0,-1),B(process.stdout,0)),n.pushUser(A),n.refreshPrompt(),n.showAssistantLoading();const Vt=we(A),Tt=ss(t,Vt);if(Nt.length=0,!String(Tt||"").trim()){n.dismissTransientLoading(),n.refreshPrompt();return}if(Tt.length>K){n.pushAssistant(e.red(`Input too long after command expansion (${Tt.length} chars).`)),n.pushSystem(e.gray(`Try shortening the command template or user text. Limit: ${K} chars.`)),n.refreshPrompt();return}Q=!0;let V=v.systemPrompt||"You are Zibby, a helpful AI assistant.";const Xt=is(v,o);Xt&&(V+=`
65
65
 
66
- ${Xt}`);const Qt=ze({activeSkills:L,chatConfig:v,options:o});Qt&&(K+=`
66
+ ${Xt}`);const Qt=ze({activeSkills:L,chatConfig:v,options:o});Qt&&(V+=`
67
67
 
68
- ${Qt}`);const te=rs(L);if(te&&(K+=`
68
+ ${Qt}`);const te=rs(L);if(te&&(V+=`
69
69
 
70
- ${te}`),K+=`
70
+ ${te}`),V+=`
71
71
 
72
- Use provided tools when external data/actions are required. Do not claim actions without tool calls. Before using a skill's tools for the first time in a conversation, call get_skill_context(skillId) to load its full guidance.`,L.includes("chat-memory")&&(K+=`
72
+ Use provided tools when external data/actions are required. Do not claim actions without tool calls. Before using a skill's tools for the first time in a conversation, call get_skill_context(skillId) to load its full guidance.`,L.includes("chat-memory")&&(V+=`
73
73
 
74
74
  ### Memory Tool Usage (chat-memory)
75
75
  - At conversation start: call memory_brief to load recent context.
76
76
  - Before answering memory-dependent questions: call memory_recall with focused query terms.
77
77
  - When learning durable user/project facts or decisions: call memory_store.
78
78
  - Avoid storing transient chatter, filler text, or duplicate facts.
79
- - Prefer updating strong existing facts over creating near-duplicates when possible.`),L.includes("workflow-builder")&&(K+=`
79
+ - Prefer updating strong existing facts over creating near-duplicates when possible.`),L.includes("workflow-builder")&&(V+=`
80
80
 
81
81
  ### Workflow Builder (workflow-builder)
82
82
  - When users want to create, build, or scaffold an AI workflow, use the workflow-builder tools.
@@ -84,8 +84,8 @@ Use provided tools when external data/actions are required. Do not claim actions
84
84
  - Conversation flow: ask about purpose \u2192 input data \u2192 processing steps \u2192 output format \u2192 conditional logic.
85
85
  - Then call design_workflow to create a spec, review with user, then build_workflow to generate code.
86
86
  - After building: remind user about \`zibby start <name>\` (test), \`zibby deploy <name>\` (deploy), \`zibby logs\` (logs).
87
- - Use list_workflows to show existing workflows, add_node to extend them, deploy_workflow to ship.`),L.includes("chat-memory"))try{const a=$t("chat-memory");if(typeof a?.buildPromptContext=="function"){const _=Date.now();let h;et.data&&_-et.timestamp<F?(h=et.data,process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray("Using cached memory context"))):(h=await a.buildPromptContext({options:{workspace:t}},{}),et={data:h,timestamp:_},process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray("Refreshed memory context cache")));const T=String(h?.backend||"dolt");process.env.ZIBBY_VERBOSE==="true"&&(n.pushSystem(e.gray(`memory backend: ${T}`)),n.pushSystem(e.gray(`memory retrieval output: ${Et(JSON.stringify(h?.debugPreview||{}),1400)}`)),h?.error&&n.pushSystem(e.yellow(`memory backend warning: ${h.error}`))),h?.promptContext&&(K+=`
87
+ - Use list_workflows to show existing workflows, add_node to extend them, deploy_workflow to ship.`),L.includes("chat-memory"))try{const a=$t("chat-memory");if(typeof a?.buildPromptContext=="function"){const x=Date.now();let h;ot.data&&x-ot.timestamp<F?(h=ot.data,process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray("Using cached memory context"))):(h=await a.buildPromptContext({options:{workspace:t}},{}),ot={data:h,timestamp:x},process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray("Refreshed memory context cache")));const T=String(h?.backend||"dolt");process.env.ZIBBY_VERBOSE==="true"&&(n.pushSystem(e.gray(`memory backend: ${T}`)),n.pushSystem(e.gray(`memory retrieval output: ${Et(JSON.stringify(h?.debugPreview||{}),1400)}`)),h?.error&&n.pushSystem(e.yellow(`memory backend warning: ${h.error}`))),h?.promptContext&&(V+=`
88
88
 
89
- ${h.promptContext}`)}}catch(a){process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.yellow(`memory backend warning: ${String(a?.message||a)}`))}K=_t(K,ce);const Se=os(E),Ft=ns([{role:"system",content:K},...Se,{role:"user",content:Tt}]),ee=Ht(Ft),ke=Buffer.byteLength(JSON.stringify(Ft),"utf8");process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray(`payload estimate: ${ee} chars, ${ke} bytes (~${Math.round(ee/4)} tokens)`)),E.push({role:"human",content:Vt});const wt=n.enabled?(()=>{const a=()=>{};return a.setLabel=()=>{},a})():le();let at=!0;const Ct=[];let se="",bt="";const hs=50,ys=500,ws=3,bs=60,Ss=500,ks=15,$s=25,_s=4,xs=new Set([".","!","?",",",";",":"]),$e=a=>{at&&(wt(),at=!1),bt+=a},_e=(a,_)=>{if(!a){at&&wt.setLabel("thinking...");return}Ct.push(a);const h=70;let T=a;if(_&&typeof _=="object"){const S=Object.values(_).map(d=>typeof d=="string"?d:JSON.stringify(d)).join(", "),f=`${a}(${S})`;f.length<=h?T=f:T=`${a}(${S.slice(0,h-a.length-4)}...)`}T!==se&&(se=T,n.pushSystem(e.gray(`\u23BF ${T}`)),n.refreshPrompt({preserveInput:!0}),at&&n.showAssistantLoading()),at&&wt.setLabel(T)},jt=new AbortController;O=jt;try{const a=await xe("",{state:{agentType:C,config:k,cwd:t,workspace:t}},{model:k?.agent?.assistant?.model||v.model||"auto",workspace:t,skills:L,activeSkills:L,config:k,timeout:v.timeout||3e5,messages:Ft,skipPromptFragments:!0,stream:!0,onToken:$e,onToolCall:_e,signal:jt.signal});at&&wt();const _=typeof a=="string"?a:a?.structured?JSON.stringify(a.structured,null,2):a?.raw||String(a),h=bt&&bt.trim().length>0?bt.trim():_.trim(),T=cs(h,Ct)?h:as(h);n.pushAssistant(T);const b=Ct.length>0?`[tools used: ${Ct.join(", ")}]
90
- ${h}`:h;E.push({role:"ai",content:b}),Pt(t,E),It(t,L)}catch(a){if(at&&wt(),n.dismissTransientLoading(),jt.signal.aborted){ot.length===0&&n.pushAssistant(e.gray("[cancelled]"));let _="";try{const{testRunnerSkill:T}=await import("../../skills/index.js"),b=await T.handleToolCall("run_status",{runId:"all"},{options:{workspace:t}}),S=JSON.parse(b);S.runs?.length>0&&(_=`
91
- [Active test runs: ${S.runs.map(d=>`${d.runId}: ${d.ticketKey||d.spec} (${d.status})`).join(", ")}. Use run_status("all") to check progress.]`)}catch{}const h=bt.trim();h?E.push({role:"ai",content:h+_}):E.push({role:"ai",content:`[interrupted \u2014 new message]${_}`})}else{const _=String(a?.message||a||"Unknown error");/413|payload too large|request payload too large/i.test(_)?(n.pushAssistant(e.yellow("Request became too large for the proxy (413).")),n.pushSystem(e.gray("Try: /clear, then retry your command; or shorten command/context."))):n.pushAssistant(e.red(`Error: ${_}`)),E.push({role:"ai",content:`[Error: ${a.message}]`})}}finally{O=null,ut=!1}if(n.refreshPrompt(),ot.length>0){const a=ot.shift();pt=!0,setImmediate(()=>m.emit("line",a))}}catch(i){n.pushSystem(e.red(`Input handling error: ${i?.message||String(i)}`)),n.refreshPrompt()}}),m.on("SIGINT",()=>{if(O){O.abort();return}Lt()}),m.on("close",Lt);const be=()=>{process.stdin?.off?(process.stdin.off("data",xt),process.stdin.off("keypress",Ut)):process.stdin?.removeListener&&(process.stdin.removeListener("data",xt),process.stdin.removeListener("keypress",Ut))};m.on("close",be)})}export{Fs as _buildPrompt,Qe as _checkEnvKeys,Xe as _formatHistory,Us as _inferAgentType,Ds as chatCommand};
89
+ ${h.promptContext}`)}}catch(a){process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.yellow(`memory backend warning: ${String(a?.message||a)}`))}V=xt(V,ce);const Se=os(E),Ft=ns([{role:"system",content:V},...Se,{role:"user",content:Tt}]),ee=Ht(Ft),ke=Buffer.byteLength(JSON.stringify(Ft),"utf8");process.env.ZIBBY_VERBOSE==="true"&&n.pushSystem(e.gray(`payload estimate: ${ee} chars, ${ke} bytes (~${Math.round(ee/4)} tokens)`)),E.push({role:"human",content:Vt});const wt=n.enabled?(()=>{const a=()=>{};return a.setLabel=()=>{},a})():le();let lt=!0;const Ct=[];let se="",bt="";const hs=50,ys=500,ws=3,bs=60,Ss=500,ks=15,$s=25,xs=4,_s=new Set([".","!","?",",",";",":"]),$e=a=>{lt&&(wt(),lt=!1),bt+=a},xe=(a,x)=>{if(!a){lt&&wt.setLabel("thinking...");return}Ct.push(a);const h=70;let T=a;if(x&&typeof x=="object"){const S=Object.values(x).map(d=>typeof d=="string"?d:JSON.stringify(d)).join(", "),f=`${a}(${S})`;f.length<=h?T=f:T=`${a}(${S.slice(0,h-a.length-4)}...)`}T!==se&&(se=T,n.pushSystem(e.gray(`\u23BF ${T}`)),n.refreshPrompt({preserveInput:!0}),lt&&n.showAssistantLoading()),lt&&wt.setLabel(T)},jt=new AbortController;O=jt;try{const a=await _e("",{state:{agentType:C,config:k,cwd:t,workspace:t}},{model:k?.agent?.assistant?.model||v.model||"auto",workspace:t,skills:L,activeSkills:L,config:k,timeout:v.timeout||3e5,messages:Ft,skipPromptFragments:!0,stream:!0,onToken:$e,onToolCall:xe,signal:jt.signal});lt&&wt();const x=typeof a=="string"?a:a?.structured?JSON.stringify(a.structured,null,2):a?.raw||String(a),h=bt&&bt.trim().length>0?bt.trim():x.trim(),T=cs(h,Ct)?h:as(h);n.pushAssistant(T);const b=Ct.length>0?`[tools used: ${Ct.join(", ")}]
90
+ ${h}`:h;E.push({role:"ai",content:b}),Pt(t,E),It(t,L)}catch(a){if(lt&&wt(),n.dismissTransientLoading(),jt.signal.aborted){Y.length===0&&n.pushAssistant(e.gray("[cancelled]"));let x="";try{const{testRunnerSkill:T}=await import("../../skills/index.js"),b=await T.handleToolCall("run_status",{runId:"all"},{options:{workspace:t}}),S=JSON.parse(b);S.runs?.length>0&&(x=`
91
+ [Active test runs: ${S.runs.map(d=>`${d.runId}: ${d.ticketKey||d.spec} (${d.status})`).join(", ")}. Use run_status("all") to check progress.]`)}catch{}const h=bt.trim();h?E.push({role:"ai",content:h+x}):E.push({role:"ai",content:`[interrupted \u2014 new message]${x}`})}else{const x=String(a?.message||a||"Unknown error");/413|payload too large|request payload too large/i.test(x)?(n.pushAssistant(e.yellow("Request became too large for the proxy (413).")),n.pushSystem(e.gray("Try: /clear, then retry your command; or shorten command/context."))):n.pushAssistant(e.red(`Error: ${x}`)),E.push({role:"ai",content:`[Error: ${a.message}]`})}}finally{O=null,Q=!1}if(n.refreshPrompt(),Y.length>0){const a=Y.shift();pt=!0,setImmediate(()=>m.emit("line",a))}}catch(i){n.pushSystem(e.red(`Input handling error: ${i?.message||String(i)}`)),n.refreshPrompt()}}),m.on("SIGINT",()=>{if(O){O.abort();return}Lt()}),m.on("close",Lt);const be=()=>{process.stdin?.off?(process.stdin.off("data",_t),process.stdin.off("keypress",Ut)):process.stdin?.removeListener&&(process.stdin.removeListener("data",_t),process.stdin.removeListener("keypress",Ut))};m.on("close",be)})}export{Fs as _buildPrompt,Qe as _checkEnvKeys,Xe as _formatHistory,Us as _inferAgentType,Ds as chatCommand};
@@ -0,0 +1,15 @@
1
+ import l from"dotenv";import{getApiUrl as i}from"../config/environments.js";l.config();function p(t){const r=t.apiKey||process.env.ZIBBY_API_KEY;return r||(console.log(`
2
+ Error: API key is required`),console.log(` Set ZIBBY_API_KEY environment variable or use --api-key flag
3
+ `),process.exit(1)),{apiKey:r}}async function f(t={}){const{apiKey:r}=p(t),s=i();try{const n=await fetch(`${s}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(!n.ok){const e=await n.json().catch(()=>({}));console.log(`
4
+ Error: ${e.message||n.statusText}
5
+ `),process.exit(1)}let o=await n.json();if(Array.isArray(o)||(o.projects&&Array.isArray(o.projects)?o=o.projects:o.data&&Array.isArray(o.data)?o=o.data:(console.log(`
6
+ Error: Unexpected response format
7
+ `),console.log(" Response:",JSON.stringify(o,null,2)),process.exit(1))),!o||o.length===0){console.log(`
8
+ No projects found
9
+ `);return}console.log(`
10
+ Projects
11
+ `),console.log(" ".padEnd(80,"-")),console.log(`${" ID".padEnd(30)+"Name".padEnd(30)}Created`),console.log(" ".padEnd(80,"-"));for(const e of o){const a=e.createdAt?new Date(e.createdAt).toLocaleDateString():"-",c=e.projectId||e.id||"";console.log(` ${c.padEnd(28)}${(e.name||"-").padEnd(30)}${a}`)}console.log(" ".padEnd(80,"-")),console.log(`
12
+ Total: ${o.length} project${o.length===1?"":"s"}
13
+ `)}catch(n){console.log(`
14
+ Error: ${n.message}
15
+ `),process.exit(1)}}export{f as projectListCommand};
@@ -1,45 +1,47 @@
1
- import{readFileSync as _,writeFileSync as j,existsSync as v,mkdirSync as z}from"fs";import{resolve as A,join as y}from"path";import o from"chalk";import k from"ora";import P from"dotenv";import{getApiUrl as b,getCurrentEnvironment as E}from"../config/environments.js";import{validateGraphConfig as B}from"@zibby/core/framework/graph-compiler.js";import{generateWorkflowCode as J,generateNodeConfigsJson as N}from"@zibby/core/framework/code-generator.js";import"@zibby/core/templates/register-nodes.js";P.config();function x(s){const e=s.apiKey||process.env.ZIBBY_API_KEY;e||(console.log(o.red(`
1
+ import{readFileSync as T,writeFileSync as k,existsSync as b,mkdirSync as D}from"fs";import{resolve as F,join as h}from"path";import o from"chalk";import m from"ora";import P from"dotenv";import z from"inquirer";import{getApiUrl as v,getCurrentEnvironment as E}from"../config/environments.js";import{validateGraphConfig as U}from"@zibby/core/framework/graph-compiler.js";import{generateWorkflowCode as J,generateNodeConfigsJson as Y}from"@zibby/core/framework/code-generator.js";import"@zibby/core/templates/register-nodes.js";P.config();async function N(t){const n=v(),a=m("Fetching projects...").start();try{const i=await fetch(`${n}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});i.ok||(a.fail("Failed to fetch projects"),process.exit(1));let e=await i.json();Array.isArray(e)||(e.projects&&Array.isArray(e.projects)?e=e.projects:e.data&&Array.isArray(e.data)?e=e.data:(a.fail("Unexpected response format"),process.exit(1))),(!e||e.length===0)&&(a.fail("No projects found"),process.exit(1)),a.stop();const l=e.map(s=>({name:`${s.name||"Unnamed"} (${s.id||"no-id"})`,value:s.id})),{projectId:p}=await z.prompt([{type:"list",name:"projectId",message:"Select a project:",choices:l}]);return p}catch(i){a.fail(`Error: ${i.message}`),process.exit(1)}}function A(t){const n=t.apiKey||process.env.ZIBBY_API_KEY;n||(console.log(o.red(`
2
2
  ZIBBY_API_KEY not set`)),console.log(o.gray(` Add to .env: ZIBBY_API_KEY=zby_xxx
3
- `)),process.exit(1));const f=s.project||process.env.ZIBBY_PROJECT_ID;return f||(console.log(o.red(`
3
+ `)),process.exit(1));const a=t.project||process.env.ZIBBY_PROJECT_ID;return a||(console.log(o.red(`
4
4
  --project or ZIBBY_PROJECT_ID is required`)),console.log(o.gray(` Example: zibby workflow download --project <id> --type analysis
5
- `)),process.exit(1)),{apiKey:e,projectId:f}}const C=["analysis","implementation","run_test"],U=/^[a-z][a-z0-9_-]{0,62}[a-z0-9]$/;function D(s){const e=s.type;return e||(console.log(o.red(`
6
- --type is required`)),console.log(o.gray(` Built-in types: ${C.join(", ")}`)),console.log(o.gray(` Custom workflows: any lowercase slug (e.g., ticket-triage)
7
- `)),process.exit(1)),!C.includes(e)&&!U.test(e)&&(console.log(o.red(`
8
- Invalid workflow type: "${e}"`)),console.log(o.gray(` Built-in: ${C.join(", ")}`)),console.log(o.gray(` Custom: lowercase letters, digits, hyphens (2\u201364 chars)
9
- `)),process.exit(1)),e}async function H(s){const e=E(),{apiKey:f,projectId:d}=x(s),n=D(s);console.log(o.bold.cyan(`
5
+ `)),process.exit(1)),{apiKey:n,projectId:a}}async function K(t){const n=t.apiKey||process.env.ZIBBY_API_KEY;n||(console.log(o.red(`
6
+ ZIBBY_API_KEY not set`)),console.log(o.gray(` Add to .env: ZIBBY_API_KEY=zby_xxx
7
+ `)),process.exit(1));let a=t.project||process.env.ZIBBY_PROJECT_ID;return a||(a=await N(n)),{apiKey:n,projectId:a}}const I=["analysis","implementation","run_test"],O=/^[a-z][a-z0-9_-]{0,62}[a-z0-9]$/;function C(t){const n=t.type;return n||(console.log(o.red(`
8
+ --type is required`)),console.log(o.gray(` Built-in types: ${I.join(", ")}`)),console.log(o.gray(` Custom workflows: any lowercase slug (e.g., ticket-triage)
9
+ `)),process.exit(1)),!I.includes(n)&&!O.test(n)&&(console.log(o.red(`
10
+ Invalid workflow type: "${n}"`)),console.log(o.gray(` Built-in: ${I.join(", ")}`)),console.log(o.gray(` Custom: lowercase letters, digits, hyphens (2\u201364 chars)
11
+ `)),process.exit(1)),n}async function oo(t){const n=E(),{apiKey:a,projectId:i}=A(t),e=C(t);console.log(o.bold.cyan(`
10
12
  Zibby Workflow Download
11
- `)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(e.name)}`)),console.log(o.white(` Project: ${o.cyan(d)}`)),console.log(o.white(` Type: ${o.cyan(n)}`)),console.log(o.gray(" ".padEnd(52,"-")));const l=k(" Fetching workflow from cloud...").start();try{const p=b(),r=await fetch(`${p}/projects/${d}/workflows/${n}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`}});if(!r.ok){const a=await r.text();l.fail(` API error: ${r.status}`),console.log(o.red(` ${a}
12
- `)),process.exit(1)}const t=await r.json();!t.graph&&t.isDefault?l.info(" No custom workflow saved -- downloading default graph"):l.succeed(` Fetched workflow (v${t.version||0})`);const i=t.graph||null;if(!i){console.log(o.yellow(`
13
+ `)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(n.name)}`)),console.log(o.white(` Project: ${o.cyan(i)}`)),console.log(o.white(` Type: ${o.cyan(e)}`)),console.log(o.gray(" ".padEnd(52,"-")));const l=m(" Fetching workflow from cloud...").start();try{const p=v(),s=await fetch(`${p}/projects/${i}/workflows/${e}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`}});if(!s.ok){const c=await s.text();l.fail(` API error: ${s.status}`),console.log(o.red(` ${c}
14
+ `)),process.exit(1)}const r=await s.json();!r.graph&&r.isDefault?l.info(" No custom workflow saved -- downloading default graph"):l.succeed(` Fetched workflow (v${r.version||0})`);const d=r.graph||null;if(!d){console.log(o.yellow(`
13
15
  No graph config available for this workflow.`)),console.log(o.gray(" The project is using the built-in default graph.")),console.log(o.gray(` Edit the graph in the UI first, or use --include-default to download the default.
14
- `)),s.includeDefault||process.exit(0),l.start(" Fetching default graph...");const{getDefaultGraph:a}=await import("@zibby/core/templates/graphs/index.js"),w=a(n);return w||(l.fail(` No default graph found for type "${n}"`),process.exit(1)),F(n,{graph:w,version:0,isDefault:!0,projectId:d,workflowType:n},s)}return F(n,{graph:i,version:t.version||0,isDefault:t.isDefault||!1,projectId:d,workflowType:n},s)}catch(p){l.fail(" Download failed"),console.log(o.red(`
16
+ `)),t.includeDefault||process.exit(0),l.start(" Fetching default graph...");const{getDefaultGraph:c}=await import("@zibby/core/templates/graphs/index.js"),w=c(e);return w||(l.fail(` No default graph found for type "${e}"`),process.exit(1)),S(e,{graph:w,version:0,isDefault:!0,projectId:i,workflowType:e},t)}return S(e,{graph:d,version:r.version||0,isDefault:r.isDefault||!1,projectId:i,workflowType:e},t)}catch(p){l.fail(" Download failed"),console.log(o.red(`
15
17
  ${p.message}
16
- `)),process.exit(1)}}function F(s,e,f){const d=process.cwd(),n=f.output||y(d,".zibby");v(n)||z(n,{recursive:!0});const l={projectId:e.projectId,workflowType:e.workflowType,version:e.version,isDefault:e.isDefault},p=`workflow-${s}.js`,r=y(n,p),t=J(e.graph,l);j(r,t,"utf-8");const i=e.graph.nodeConfigs||{},a=N(i),w=`workflow-${s}.config.json`,m=y(n,w);j(m,`${JSON.stringify(a,null,2)}
17
- `,"utf-8");const $=`workflow-${s}.json`,c=y(n,$),g={_meta:{...l,downloadedAt:new Date().toISOString()},...e.graph};j(c,`${JSON.stringify(g,null,2)}
18
+ `)),process.exit(1)}}function S(t,n,a){const i=process.cwd(),e=a.output||h(i,".zibby");b(e)||D(e,{recursive:!0});const l={projectId:n.projectId,workflowType:n.workflowType,version:n.version,isDefault:n.isDefault},p=`workflow-${t}.js`,s=h(e,p),r=J(n.graph,l);k(s,r,"utf-8");const d=n.graph.nodeConfigs||{},c=Y(d),w=`workflow-${t}.config.json`,$=h(e,w);k($,`${JSON.stringify(c,null,2)}
19
+ `,"utf-8");const j=`workflow-${t}.json`,g=h(e,j),f={_meta:{...l,downloadedAt:new Date().toISOString()},...n.graph};k(g,`${JSON.stringify(f,null,2)}
18
20
  `,"utf-8"),console.log(o.green(`
19
- Generated workflow files:`)),console.log(o.white(` ${o.bold(r)}`)),console.log(o.gray(" Executable graph with inline tool bindings")),console.log(o.white(` ${o.bold(m)}`)),console.log(o.gray(" Extra prompt instructions & runtime config")),console.log(o.white(` ${o.bold(c)}`)),console.log(o.gray(" Raw JSON config (for upload back to cloud)")),console.log(""),console.log(o.gray(` Version: ${e.version}`)),console.log(o.gray(` Nodes: ${e.graph.nodes?.length||0}`)),console.log(o.gray(` Edges: ${e.graph.edges?.length||0}
20
- `)),console.log(o.white(" To run locally:")),console.log(o.cyan(` zibby analyze --workflow ${r}
21
- `)),console.log(o.white(" To upload changes back:")),console.log(o.cyan(` zibby workflow upload --project ${e.projectId} --type ${s}
22
- `))}async function M(s){const e=E(),{apiKey:f,projectId:d}=x(s),n=D(s);console.log(o.bold.cyan(`
21
+ Generated workflow files:`)),console.log(o.white(` ${o.bold(s)}`)),console.log(o.gray(" Executable graph with inline tool bindings")),console.log(o.white(` ${o.bold($)}`)),console.log(o.gray(" Extra prompt instructions & runtime config")),console.log(o.white(` ${o.bold(g)}`)),console.log(o.gray(" Raw JSON config (for upload back to cloud)")),console.log(""),console.log(o.gray(` Version: ${n.version}`)),console.log(o.gray(` Nodes: ${n.graph.nodes?.length||0}`)),console.log(o.gray(` Edges: ${n.graph.edges?.length||0}
22
+ `)),console.log(o.white(" To run locally:")),console.log(o.cyan(` zibby analyze --workflow ${s}
23
+ `)),console.log(o.white(" To upload changes back:")),console.log(o.cyan(` zibby workflow upload --project ${n.projectId} --type ${t}
24
+ `))}async function eo(t){const n=E(),{apiKey:a,projectId:i}=await K(t),e=C(t);console.log(o.bold.cyan(`
23
25
  Zibby Workflow Upload
24
- `)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(e.name)}`)),console.log(o.white(` Project: ${o.cyan(d)}`)),console.log(o.white(` Type: ${o.cyan(n)}`)),console.log(o.gray(" ".padEnd(52,"-")));const l=process.cwd(),p=y(l,".zibby",`workflow-${n}.json`),r=y(l,".zibby",`workflow-${n}.js`),t=s.file||(v(r)?r:p);v(t)||(console.log(o.red(`
25
- File not found: ${t}`)),console.log(o.gray(` Download a workflow first: zibby workflow download --project <id> --type <type>
26
- `)),process.exit(1));const i=t.endsWith(".js")||t.endsWith(".mjs");let a;if(i){const c=k(" Loading JS workflow module...").start();try{const{pathToFileURL:g}=await import("url"),u=await import(g(A(t)).href),h=u.buildGraph();a=h.serialize();const I=u.nodeConfigs||{};if(Object.keys(I).length>0)for(const[S,T]of Object.entries(I))a.nodeConfigs[S]={...T,...a.nodeConfigs[S]};c.succeed(` Loaded JS module (${h.nodes.size} nodes)`)}catch(g){c.fail(" Failed to load JS module"),console.log(o.red(`
27
- ${g.message}
28
- `)),process.exit(1)}}else{let c;try{c=JSON.parse(_(t,"utf-8"))}catch(h){console.log(o.red(`
29
- Failed to parse ${t}: ${h.message}
30
- `)),process.exit(1)}const{_meta:g,...u}=c;a=u}(!a.nodes||!a.edges)&&(console.log(o.red(`
26
+ `)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(n.name)}`)),console.log(o.white(` Project: ${o.cyan(i)}`)),console.log(o.white(` Type: ${o.cyan(e)}`)),console.log(o.gray(" ".padEnd(52,"-")));const l=process.cwd(),p=h(l,".zibby",`workflow-${e}.json`),s=h(l,".zibby",`workflow-${e}.js`),r=t.file||(b(s)?s:p);b(r)||(console.log(o.red(`
27
+ File not found: ${r}`)),console.log(o.gray(` Download a workflow first: zibby workflow download --project <id> --type <type>
28
+ `)),process.exit(1));const d=r.endsWith(".js")||r.endsWith(".mjs");let c;if(d){const g=m(" Loading JS workflow module...").start();try{const{pathToFileURL:f}=await import("url"),u=await import(f(F(r)).href),y=u.buildGraph();c=y.serialize();const x=u.nodeConfigs||{};if(Object.keys(x).length>0)for(const[_,B]of Object.entries(x))c.nodeConfigs[_]={...B,...c.nodeConfigs[_]};g.succeed(` Loaded JS module (${y.nodes.size} nodes)`)}catch(f){g.fail(" Failed to load JS module"),console.log(o.red(`
29
+ ${f.message}
30
+ `)),process.exit(1)}}else{let g;try{g=JSON.parse(T(r,"utf-8"))}catch(y){console.log(o.red(`
31
+ Failed to parse ${r}: ${y.message}
32
+ `)),process.exit(1)}const{_meta:f,...u}=g;c=u}(!c.nodes||!c.edges)&&(console.log(o.red(`
31
33
  Invalid workflow file: missing nodes or edges`)),console.log(o.gray(` The file should contain { nodes: [...], edges: [...], nodeConfigs: {...} }
32
34
  `)),process.exit(1)),console.log(o.gray(`
33
- File: ${t}`)),console.log(o.gray(` Format: ${i?"JavaScript (serialized via graph.serialize())":"JSON"}`)),console.log(o.gray(` Nodes: ${a.nodes.length}`)),console.log(o.gray(` Edges: ${a.edges.length}`));const w=k(" Validating graph...").start(),m=B(a);if(!m.valid){w.fail(" Graph validation failed"),console.log("");for(const c of m.errors)console.log(o.red(` ${c}`));console.log(o.gray(`
35
+ File: ${r}`)),console.log(o.gray(` Format: ${d?"JavaScript (serialized via graph.serialize())":"JSON"}`)),console.log(o.gray(` Nodes: ${c.nodes.length}`)),console.log(o.gray(` Edges: ${c.edges.length}`));const w=m(" Validating graph...").start(),$=U(c);if(!$.valid){w.fail(" Graph validation failed"),console.log("");for(const g of $.errors)console.log(o.red(` ${g}`));console.log(o.gray(`
34
36
  Fix the errors above and try again.
35
- `)),process.exit(1)}w.succeed(" Graph is valid");const $=k(" Uploading to cloud...").start();try{const c=b(),g=await fetch(`${c}/projects/${d}/workflows/${n}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`},body:JSON.stringify({graph:a})});if(!g.ok){const h=await g.text();$.fail(` API error: ${g.status}`),console.log(o.red(` ${h}
36
- `)),process.exit(1)}const u=await g.json();$.succeed(` Uploaded successfully (v${u.version})`),console.log(o.green(`
37
- Workflow "${n}" updated to version ${u.version}`)),console.log(o.gray(` Project: ${d}
38
- `))}catch(c){$.fail(" Upload failed"),console.log(o.red(`
39
- ${c.message}
40
- `)),process.exit(1)}}const O=["analysis","implementation","run_test"];async function Q(s){const e=E(),{apiKey:f,projectId:d}=x(s);console.log(o.bold.cyan(`
37
+ `)),process.exit(1)}w.succeed(" Graph is valid");const j=m(" Uploading to cloud...").start();try{const g=v(),f=await fetch(`${g}/projects/${i}/workflows/${e}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({graph:c})});if(!f.ok){const y=await f.text();j.fail(` API error: ${f.status}`),console.log(o.red(` ${y}
38
+ `)),process.exit(1)}const u=await f.json();j.succeed(` Uploaded successfully (v${u.version})`),console.log(o.green(`
39
+ Workflow "${e}" updated to version ${u.version}`)),console.log(o.gray(` Project: ${i}
40
+ `))}catch(g){j.fail(" Upload failed"),console.log(o.red(`
41
+ ${g.message}
42
+ `)),process.exit(1)}}const W=["analysis","implementation","run_test"];async function no(t){const n=E(),{apiKey:a,projectId:i}=A(t);console.log(o.bold.cyan(`
41
43
  Zibby Workflows
42
- `));const n=k(" Fetching workflows...").start();try{const l=b(),p=[];for(const r of O){const t=await fetch(`${l}/projects/${d}/workflows/${r}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f}`}});if(t.ok){const i=await t.json();p.push({type:r,version:i.version||0,isDefault:i.isDefault!==!1&&!i.graph,nodes:i.graph?.nodes?.length||0,updatedAt:i.updatedAt||null})}}n.succeed(` Fetched workflows
43
- `),console.log(o.gray(" ".padEnd(70,"-"))),console.log(o.white(" Type".padEnd(20))+o.white("Version".padEnd(10))+o.white("Nodes".padEnd(10))+o.white("Status".padEnd(15))+o.white("Updated")),console.log(o.gray(" ".padEnd(70,"-")));for(const r of p){const t=r.isDefault?o.gray("default"):o.green("custom"),i=r.updatedAt?new Date(r.updatedAt).toLocaleDateString():o.gray("-");console.log(` ${o.cyan(r.type.padEnd(18))}${String(r.version).padEnd(10)}${String(r.nodes).padEnd(10)}${t.padEnd(15)}${i}`)}console.log(o.gray(" ".padEnd(70,"-"))),console.log("")}catch(l){n.fail(" Failed to fetch workflows"),console.log(o.red(`
44
+ `));const e=m(" Fetching workflows...").start();try{const l=v(),p=[];for(const s of W){const r=await fetch(`${l}/projects/${i}/workflows/${s}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`}});if(r.ok){const d=await r.json();p.push({type:s,version:d.version||0,isDefault:d.isDefault!==!1&&!d.graph,nodes:d.graph?.nodes?.length||0,updatedAt:d.updatedAt||null})}}e.succeed(` Fetched workflows
45
+ `),console.log(o.gray(" ".padEnd(70,"-"))),console.log(o.white(" Type".padEnd(20))+o.white("Version".padEnd(10))+o.white("Nodes".padEnd(10))+o.white("Status".padEnd(15))+o.white("Updated")),console.log(o.gray(" ".padEnd(70,"-")));for(const s of p){const r=s.isDefault?o.gray("default"):o.green("custom"),d=s.updatedAt?new Date(s.updatedAt).toLocaleDateString():o.gray("-");console.log(` ${o.cyan(s.type.padEnd(18))}${String(s.version).padEnd(10)}${String(s.nodes).padEnd(10)}${r.padEnd(15)}${d}`)}console.log(o.gray(" ".padEnd(70,"-"))),console.log("")}catch(l){e.fail(" Failed to fetch workflows"),console.log(o.red(`
44
46
  ${l.message}
45
- `)),process.exit(1)}}export{H as workflowDownloadCommand,Q as workflowListCommand,M as workflowUploadCommand};
47
+ `)),process.exit(1)}}export{oo as workflowDownloadCommand,no as workflowListCommand,eo as workflowUploadCommand};
@@ -1,24 +1,14 @@
1
- import{existsSync as m}from"fs";import{readFile as B,readdir as P}from"fs/promises";import{join as y,resolve as T,relative as x}from"path";import{pathToFileURL as z}from"url";import o from"chalk";import h from"ora";import C from"dotenv";import{getApiUrl as I,getCurrentEnvironment as E}from"../../config/environments.js";import{getSessionToken as S}from"../../config/config.js";C.config();function A(r){const t=r.apiKey||process.env.ZIBBY_API_KEY||S();t||(console.log(o.red(`
2
- Not authenticated`)),console.log(o.gray(` Run: zibby login
3
- `)),process.exit(1));const e=r.project||process.env.ZIBBY_PROJECT_ID;return e||(console.log(o.red(`
4
- --project or ZIBBY_PROJECT_ID is required`)),console.log(o.gray(` Example: zibby deploy my-workflow --project <id>
5
- `)),process.exit(1)),{apiKey:t,projectId:e}}function O(r){const t=process.cwd();return y(t,".zibby","workflows",r)}async function U(r,t){const e=y(r,"workflow.json");if(!m(e))return{name:t,triggers:{api:!0}};const l=await B(e,"utf-8");return JSON.parse(l)}async function D(r){const t={};async function e(l){const u=await P(l,{withFileTypes:!0});for(const g of u){const i=y(l,g.name);if(g.isDirectory())await e(i);else if(/\.(mjs|js|json)$/.test(g.name)){const f=x(r,i);t[f]=await B(i,"utf-8")}}}return await e(r),t}async function Z(r,t){r||(console.log(o.red(`
6
- Workflow name is required`)),console.log(o.gray(" Usage: zibby deploy <workflow-name>")),console.log(o.gray(` Example: zibby deploy ticket-triage
7
- `)),process.exit(1));const e=r.toLowerCase(),l=O(e);m(l)||(console.log(o.red(`
8
- Workflow not found: .zibby/workflows/${e}/`)),console.log(o.gray(" Create one first:")),console.log(o.cyan(` zibby g workflow ${e}
9
- `)),process.exit(1));const u=E(),{apiKey:g,projectId:i}=A(t);console.log(o.bold.cyan(`
10
- Zibby Workflow Deploy
11
- `)),console.log(o.gray(" ".padEnd(56,"-"))),console.log(o.white(` Environment: ${o.cyan(u.name)}`)),console.log(o.white(` Project: ${o.cyan(i)}`)),console.log(o.white(` Workflow: ${o.cyan(e)}`)),console.log(o.gray(" ".padEnd(56,"-")));const f=h(" Loading workflow module...").start();let b,$;try{$=await U(l,e);const n=y(l,"graph.mjs");if(!m(n))throw new Error(`graph.mjs not found in .zibby/workflows/${e}/`);const s=await import(z(T(n)).href),a=$.entryClass,c=a&&s[a]||s.default||Object.values(s).find(v=>typeof v=="function"&&v.prototype?.buildGraph);if(!c)throw new Error("No WorkflowAgent class found in graph.mjs");const j=new c().buildGraph();b=j.serialize(),f.succeed(` Loaded ${c.name} (${j.nodes.size} nodes)`)}catch(n){f.fail(" Failed to load workflow"),console.log(o.red(`
12
- ${n.message}
13
- `)),process.exit(1)}const k=h(" Bundling source files...").start();let p;try{p=await D(l);const n=Object.keys(p).length,s=(Buffer.byteLength(JSON.stringify(p),"utf-8")/1024).toFixed(1);k.succeed(` Bundled ${n} files (${s} KB)`)}catch(n){k.fail(" Failed to bundle sources"),console.log(o.red(`
14
- ${n.message}
15
- `)),process.exit(1)}const w=h(" Deploying to cloud...").start();try{const n=I(),s=await fetch(`${n}/projects/${i}/workflows/${e}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${g}`},body:JSON.stringify({graph:b,sources:p})});if(!s.ok){const d=await s.text();w.fail(` API error: ${s.status}`),console.log(o.red(` ${d}
16
- `)),process.exit(1)}const a=await s.json();w.succeed(` Deployed successfully (v${a.version})`);const c=`${n}/projects/${i}/workflows/${e}/trigger`;if(console.log(o.green(`
17
- Workflow "${e}" deployed to version ${a.version}`)),console.log(o.white(`
18
- Trigger URL (API):`)),console.log(o.cyan(` POST ${c}`)),a.subdomain){const d=`https://${a.subdomain}.workflows.zibby.app`;console.log(o.white(`
19
- Trigger URL (subdomain):`)),console.log(o.cyan(` POST ${d}`))}console.log(o.white(`
20
- Test with:`)),console.log(o.gray(` curl -X POST ${c} \\`)),console.log(o.gray(' -H "Authorization: Bearer $ZIBBY_API_KEY" \\')),console.log(o.gray(' -H "Content-Type: application/json" \\')),console.log(o.gray(` -d '{"input": {"key": "value"}}'`)),console.log(o.white(`
21
- Tail logs:`)),console.log(o.gray(` zibby logs <jobId> --project ${i}
22
- `))}catch(n){w.fail(" Deploy failed"),console.log(o.red(`
23
- ${n.message}
24
- `)),process.exit(1)}}export{Z as deployWorkflowCommand};
1
+ import{existsSync as i,readFileSync as I}from"fs";import{join as n}from"path";import a from"chalk";import v from"ora";import W from"dotenv";import{select as D}from"@inquirer/prompts";import{loadUserConfig as G}from"../../config/config-loader.js";import{getApiUrl as _}from"../../config/environments.js";W.config();async function O(c){const b=_(),p=v("Fetching projects...").start();try{const g=await fetch(`${b}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`}});g.ok||(p.fail("Failed to fetch projects"),process.exit(1));let o=await g.json();Array.isArray(o)||(o.projects&&Array.isArray(o.projects)?o=o.projects:o.data&&Array.isArray(o.data)?o=o.data:(p.fail("Unexpected response format"),process.exit(1))),(!o||o.length===0)&&(p.fail("No projects found"),process.exit(1)),p.succeed(`Found ${o.length} project${o.length===1?"":"s"}`),console.log("");const m=o.map(l=>{const k=l.projectId||l.id||l._id||"unknown";return{name:`${l.name||l.projectName||"Unnamed"} (${k})`,value:k}});return await D({message:"Select a project to deploy to:",choices:m})}catch(g){p.fail(`Error: ${g.message}`),process.exit(1)}}async function q(c,b={}){const p=process.cwd(),g=b.apiKey||process.env.ZIBBY_API_KEY;g||(console.log(`
2
+ Error: ZIBBY_API_KEY not set`),console.log(` Add to .env or use --api-key flag
3
+ `),process.exit(1));let o=".zibby/workflows";try{o=(await G(p))?.paths?.workflows||".zibby/workflows"}catch{}if(!c){const t=n(p,o);i(t)||(console.log(`
4
+ Error: No workflows found in ${o}/`),console.log(` Create one with: zibby g workflow <name>
5
+ `),process.exit(1));const{readdir:r,stat:w}=await import("fs/promises"),C=await r(t),h=[];for(const u of C){const f=n(t,u);if(!(await w(f)).isDirectory())continue;(i(n(f,"graph.mjs"))||i(n(f,"graph.js")))&&h.push(u)}h.length===0&&(console.log(`
6
+ Error: No workflows found in ${o}/`),console.log(` Create one with: zibby g workflow <name>
7
+ `),process.exit(1)),console.log(""),c=await D({message:"Select a workflow to deploy:",choices:h.map(u=>({name:u,value:u}))})}let m=b.project||process.env.ZIBBY_PROJECT_ID;m||(console.log(""),m=await O(g));const d=n(p,o,c);i(d)||(console.log(`
8
+ Error: Workflow not found: ${o}/${c}`),console.log(` Run: zibby workflow list
9
+ `),process.exit(1));const l=n(d,"graph.mjs"),k=n(d,"workflow.json");i(l)||(console.log(`
10
+ Error: graph.mjs not found in ${o}/${c}/`),process.exit(1)),console.log(`
11
+ Deploying Workflow
12
+ `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${c}`),console.log(` Project: ${m}`),console.log(" ".padEnd(60,"-")),console.log("");const s=v("Validating workflow...").start(),$=I(l,"utf-8");if($.includes("@zibby/core")||$.includes("@zibby/skills")){const t=n(d,"package.json");i(t)||(s.fail("Missing package.json"),console.log(""),console.log(a.red(" \u2717 graph.mjs imports @zibby packages but no package.json found")),console.log(""),console.log(a.yellow(" Create package.json with:")),console.log(""),console.log(a.gray(" {")),console.log(a.gray(' "type": "module",')),console.log(a.gray(' "dependencies": {')),console.log(a.gray(' "@zibby/core": "workspace:*"')),console.log(a.gray(" }")),console.log(a.gray(" }")),console.log(""),process.exit(1));const r=JSON.parse(I(t,"utf-8"));!{...r.dependencies,...r.devDependencies}["@zibby/core"]&&$.includes("@zibby/core")&&(s.fail("Missing @zibby/core dependency"),console.log(""),console.log(a.red(" \u2717 graph.mjs imports @zibby/core but it's not in package.json")),console.log(""),console.log(a.yellow(" Add to package.json dependencies:")),console.log(a.gray(' "@zibby/core": "workspace:*"')),console.log(""),process.exit(1))}s.text="Loading workflow graph...";try{const{pathToFileURL:t}=await import("url"),r=await import(t(l).href);let w;if(r.default)if(typeof r.default=="function"){const e=r.default.prototype;e&&e.buildGraph?w=new r.default:w=r.default()}else s.fail("graph.mjs must export a class or factory function"),process.exit(1);else{const e=Object.values(r).find(j=>j.prototype&&j.prototype.buildGraph);e?w=new e:(s.fail("graph.mjs must export a WorkflowAgent class or factory function"),process.exit(1))}const h=w.buildGraph().serialize(),{readdir:u,readFile:f}=await import("fs/promises"),y={};s.text="Packaging workflow sources...";const P=await f(l,"utf-8");if(y["graph.mjs"]=P,i(k)){const e=await f(k,"utf-8");y["workflow.json"]=e}const z=n(d,"nodes");if(i(z)){const e=await u(z);for(const j of e)if(j.endsWith(".mjs")||j.endsWith(".js")){const F=n(z,j),T=await f(F,"utf-8");y[`nodes/${j}`]=T}}const A=n(d,"package.json");if(i(A)){const e=await f(A,"utf-8");y["package.json"]=e,s.text="Including package.json for dependencies..."}const E=n(d,"package-lock.json");if(i(E)){const e=await f(E,"utf-8");y["package-lock.json"]=e}s.text=`Uploading to cloud (${h.nodes.size||Object.keys(h.nodes||{}).length} nodes, ${Object.keys(y).length} files)...`;const B=_(),x=await fetch(`${B}/projects/${m}/workflows/${c}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${g}`},body:JSON.stringify({graph:h,sources:y,isDefault:!1})});if(!x.ok){const e=await x.json().catch(()=>({}));s.fail("Deploy failed"),console.log(` Error: ${e.message||x.statusText}
13
+ `),process.exit(1)}const U=await x.json();s.succeed(`Deployed successfully (v${U.version||1})`),console.log(""),console.log(" Next steps:"),console.log(` zibby start ${c} Run locally`),console.log(" zibby workflow list View all workflows"),console.log("")}catch(t){s.fail("Deploy failed"),console.log(` Error: ${t.message}
14
+ `),process.exit(1)}}export{q as deployWorkflowCommand};
@@ -1,4 +1,4 @@
1
- import{mkdir as d,writeFile as a}from"fs/promises";import{existsSync as u}from"fs";import{join as t}from"path";import o from"chalk";import f from"ora";const h=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,c=["stellar","quantum","cosmic","nova","nebula","solar","lunar","atomic","plasma","fusion","pulse","flux","spark","blaze","ember","radiant","luminous","electric","magnetic","kinetic","neon","cyber","pixel","matrix","vector","synth","neural","prism","zenith","phoenix","catalyst","nexus","echo","wave","crystal","jade","ruby","emerald","onyx","amber","silver","turbo","lightning","thunder","storm","arcane","mystic","ethereal","celestial","swift","crimson","iron","cobalt"],m=["flow","runner","pipeline","stream","circuit","engine","beacon","forge","relay","shuttle","conduit","gateway","sentinel","scout","pilot","voyager","ranger","dispatch","signal","pulse","agent","daemon","spark","orbit","vector","nexus","matrix","grid","mesh","bridge","link","node","craft","bolt","ray","arc","wave","hook","probe","shard"];function y(){const r=c[Math.floor(Math.random()*c.length)],e=m[Math.floor(Math.random()*m.length)];return`${r}-${e}`}function w(r){return`${r.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function x(r,e){return`/**
1
+ import{mkdir as m,writeFile as l}from"fs/promises";import{existsSync as f}from"fs";import{join as n}from"path";import e from"chalk";import h from"ora";import{loadUserConfig as y}from"../../config/config-loader.js";const w=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,d=["stellar","quantum","cosmic","nova","nebula","solar","lunar","atomic","plasma","fusion","pulse","flux","spark","blaze","ember","radiant","luminous","electric","magnetic","kinetic","neon","cyber","pixel","matrix","vector","synth","neural","prism","zenith","phoenix","catalyst","nexus","echo","wave","crystal","jade","ruby","emerald","onyx","amber","silver","turbo","lightning","thunder","storm","arcane","mystic","ethereal","celestial","swift","crimson","iron","cobalt"],u=["flow","runner","pipeline","stream","circuit","engine","beacon","forge","relay","shuttle","conduit","gateway","sentinel","scout","pilot","voyager","ranger","dispatch","signal","pulse","agent","daemon","spark","orbit","vector","nexus","matrix","grid","mesh","bridge","link","node","craft","bolt","ray","arc","wave","hook","probe","shard"];function x(){const r=d[Math.floor(Math.random()*d.length)],o=u[Math.floor(Math.random()*u.length)];return`${r}-${o}`}function b(r){return`${r.split("-").map(o=>o.charAt(0).toUpperCase()+o.slice(1)).join("")}Workflow`}function k(r,o){return`/**
2
2
  * ${r}
3
3
  *
4
4
  * buildGraph() \u2014 define nodes, edges, conditional routing
@@ -21,11 +21,11 @@ export class ${r} extends WorkflowAgent {
21
21
  }
22
22
 
23
23
  async onComplete(result) {
24
- console.log(\`[${e}] workflow complete \u2014 success: \${result.success !== false}\`);
24
+ console.log(\`[${o}] workflow complete \u2014 success: \${result.success !== false}\`);
25
25
  }
26
26
  }
27
- `}function b(){return`export { exampleNode } from './example.mjs';
28
- `}function k(){return`import { z } from '@zibby/core';
27
+ `}function $(){return`export { exampleNode } from './example.mjs';
28
+ `}function j(){return`import { z } from '@zibby/core';
29
29
 
30
30
  const ExampleOutputSchema = z.object({
31
31
  summary: z.string().describe('A short summary of the result'),
@@ -44,15 +44,16 @@ Analyze the input and return a summary with a status.\`,
44
44
 
45
45
  outputSchema: ExampleOutputSchema,
46
46
  };
47
- `}function $(r,e){return`${JSON.stringify({name:r,description:`${e} workflow`,entryClass:e,triggers:{api:!0}},null,2)}
48
- `}async function W(r){let e;r?e=r.toLowerCase():(e=y(),console.log(o.gray(`
49
- No name provided \u2014 generated: ${o.white(e)}`))),h.test(e)||(console.log(o.red(`
50
- Invalid workflow name: "${r}"`)),console.log(o.gray(" Must be lowercase, start with a letter, use only a-z, 0-9, hyphens")),console.log(o.gray(" Length: 2\u201364 characters")),console.log(o.gray(` Example: ticket-triage, pr-review, deploy-checker
51
- `)),process.exit(1));const p=process.cwd(),n=t(p,".zibby","workflows",e),s=t(n,"nodes");u(n)&&(console.log(o.red(`
52
- Workflow already exists: .zibby/workflows/${e}/`)),console.log(o.gray(` Choose a different name or delete the existing folder.
53
- `)),process.exit(1));const l=w(e),i=f(` Scaffolding workflow "${e}"...`).start();try{await d(s,{recursive:!0}),await Promise.all([a(t(n,"graph.mjs"),x(l,e)),a(t(s,"index.mjs"),b()),a(t(s,"example.mjs"),k()),a(t(n,"workflow.json"),$(e,l))]),i.succeed(` Scaffolded ${o.bold(e)}`),console.log(o.green(`
54
- Created:`)),console.log(o.white(` .zibby/workflows/${e}/`)),console.log(o.gray(` graph.mjs ${l} (entry)`)),console.log(o.gray(" nodes/index.mjs barrel export")),console.log(o.gray(" nodes/example.mjs starter node (prompt + schema)")),console.log(o.gray(" workflow.json manifest")),console.log(o.white(`
55
- Next steps:`)),console.log(o.cyan(` 1. Edit nodes in .zibby/workflows/${e}/nodes/`)),console.log(o.cyan(" 2. Wire them in graph.mjs")),console.log(o.cyan(" 3. Test locally:")),console.log(o.cyan(` zibby start ${e}`)),console.log(o.cyan(" 4. Deploy to cloud:")),console.log(o.cyan(` zibby deploy ${e}
56
- `))}catch(g){i.fail(" Scaffold failed"),console.log(o.red(`
57
- ${g.message}
58
- `)),process.exit(1)}}export{W as generateWorkflowCommand};
47
+ `}function z(r,o){return`${JSON.stringify({name:r,description:`${o} workflow`,entryClass:o,triggers:{api:!0}},null,2)}
48
+ `}function N(){return`${JSON.stringify({type:"module",dependencies:{"@zibby/core":"^0.1.33"}},null,2)}
49
+ `}async function M(r){let o;r?o=r.toLowerCase():(o=x(),console.log(e.gray(`
50
+ No name provided \u2014 generated: ${e.white(o)}`))),w.test(o)||(console.log(e.red(`
51
+ Invalid workflow name: "${r}"`)),console.log(e.gray(" Must be lowercase, start with a letter, use only a-z, 0-9, hyphens")),console.log(e.gray(" Length: 2\u201364 characters")),console.log(e.gray(` Example: ticket-triage, pr-review, deploy-checker
52
+ `)),process.exit(1));const i=process.cwd();let t=".zibby/workflows";try{const a=await y(i);console.log(e.gray(` \u{1F4CB} Loaded config: workflows path = ${a?.paths?.workflows||"(not set)"}`)),t=a?.paths?.workflows||".zibby/workflows"}catch(a){console.log(e.yellow(` \u26A0\uFE0F Could not load .zibby.config.mjs: ${a.message}`)),console.log(e.gray(` Using default path: ${t}`))}const s=n(i,t,o),c=n(s,"nodes");f(s)&&(console.log(e.red(`
53
+ Workflow already exists: ${t}/${o}/`)),console.log(e.gray(` Choose a different name or delete the existing folder.
54
+ `)),process.exit(1));const p=b(o),g=h(` Scaffolding workflow "${o}"...`).start();try{await m(n(i,t),{recursive:!0}),await m(c,{recursive:!0}),await Promise.all([l(n(s,"graph.mjs"),k(p,o)),l(n(c,"index.mjs"),$()),l(n(c,"example.mjs"),j()),l(n(s,"workflow.json"),z(o,p)),l(n(s,"package.json"),N())]),g.succeed(` Scaffolded ${e.bold(o)}`),console.log(e.green(`
55
+ Created:`)),console.log(e.white(` ${t}/${o}/`)),console.log(e.gray(` graph.mjs ${p} (entry)`)),console.log(e.gray(" nodes/index.mjs barrel export")),console.log(e.gray(" nodes/example.mjs starter node (prompt + schema)")),console.log(e.gray(" workflow.json manifest")),console.log(e.gray(" package.json dependencies (@zibby/core)")),console.log(e.white(`
56
+ Next steps:`)),console.log(e.cyan(` 1. Edit nodes in ${t}/${o}/nodes/`)),console.log(e.cyan(" 2. Wire them in graph.mjs")),console.log(e.cyan(" 3. Test locally:")),console.log(e.cyan(` zibby start ${o}`)),console.log(e.cyan(" 4. Deploy to cloud:")),console.log(e.cyan(` zibby deploy ${o}
57
+ `))}catch(a){g.fail(" Scaffold failed"),console.log(e.red(`
58
+ ${a.message}
59
+ `)),process.exit(1)}}export{M as generateWorkflowCommand};
@@ -0,0 +1,19 @@
1
+ import{readdir as k,stat as b}from"fs/promises";import{existsSync as w}from"fs";import{join as p}from"path";import e from"chalk";import j from"dotenv";import{loadUserConfig as E}from"../../config/config-loader.js";import{getApiUrl as $}from"../../config/environments.js";import{getSessionToken as z}from"../../config/config.js";j.config();async function D(i={}){const g=process.cwd();let r=".zibby/workflows";try{r=(await E(g))?.paths?.workflows||".zibby/workflows"}catch{}const f=p(g,r);if(!w(f))return i.quiet?[]:(console.log(e.yellow(`
2
+ No workflows found in ${r}/`)),console.log(e.gray(` Create one with: zibby g workflow <name>
3
+ `)),[]);try{const c=await k(f),t=[];for(const n of c){const a=p(f,n);if(!(await b(a)).isDirectory())continue;const s=w(p(a,"graph.mjs"))||w(p(a,"graph.js")),d=w(p(a,"workflow.json"));!s&&!d||t.push({name:n,hasGraph:s,hasManifest:d,path:`${r}/${n}`,source:"local"})}if(i.quiet)return t;if(t.length===0)return console.log(e.yellow(`
4
+ No workflows found in ${r}/`)),console.log(e.gray(` Create one with: zibby g workflow <name>
5
+ `)),[];console.log(e.bold.cyan(`
6
+ Local Workflows (${r})
7
+ `)),console.log(e.gray(" ".padEnd(60,"-"))),console.log(e.white(" Name".padEnd(35))+e.white("Files".padEnd(25))),console.log(e.gray(" ".padEnd(60,"-")));for(const n of t){const a=[];n.hasGraph&&a.push("graph"),n.hasManifest&&a.push("manifest"),console.log(` ${e.cyan(n.name.padEnd(33))}${e.gray(a.join(", "))}`)}return console.log(e.gray(" ".padEnd(60,"-"))),console.log(e.gray(`
8
+ Total: ${t.length} workflow${t.length===1?"":"s"}
9
+ `)),console.log(e.white(" Commands:")),console.log(e.cyan(" zibby start <name> ")+e.gray("Test locally")),console.log(e.cyan(" zibby deploy <name> ")+e.gray("Deploy to cloud")),console.log(e.cyan(" zibby trigger <name> ")+e.gray("Run workflow (returns job ID)")),console.log(e.cyan(" zibby logs <jobId> ")+e.gray("Tail execution logs")),console.log(""),t}catch(c){if(i.quiet)return[];console.log(e.red(`
10
+ Error reading workflows: ${c.message}
11
+ `)),process.exit(1)}}async function B(i={}){const g=await D({...i,quiet:!0}),r=[],f=z(),c=i.apiKey||process.env.ZIBBY_API_KEY,t=f||c;if(t)try{const o=$(),s=await fetch(`${o}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});if(s.ok){const m=(await s.json()).projects||[];for(const u of m){const y=await fetch(`${o}/projects/${u.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});if(y.ok){const h=await y.json();for(const l of h)r.push({uuid:l.uuid,name:l.workflowType,projectId:u.projectId,projectName:u.name||u.projectId,version:l.version||0,isDefault:l.isDefault!==!1&&!l.graphJson,nodes:l.graphJson?JSON.parse(l.graphJson).nodes?.length:0,updatedAt:l.updatedAt||null,source:"remote"})}}}}catch{}const n=[],a=new Map(g.map(o=>[o.name,o]));for(const o of r){const s=a.has(o.name);n.push({uuid:o.uuid,name:o.name,project:o.projectName,source:s?"local+remote":"remote",status:o.isDefault?"default":"custom",nodes:o.nodes,version:o.version,hasLocal:s})}for(const[o,s]of a.entries())r.some(m=>m.name===o)||n.push({uuid:null,name:s.name,project:"-",source:"local",status:s.hasGraph?"ready":"incomplete",nodes:"-",version:"-",hasLocal:!0});if(n.length===0){console.log(`
12
+ No workflows found
13
+ `),console.log(` Create one with: zibby g workflow <name>
14
+ `);return}console.log(`
15
+ Workflows
16
+ `),console.log(" ".padEnd(130,"-")),console.log(`${" UUID".padEnd(40)+"Name".padEnd(20)+"Project".padEnd(20)+"Source".padEnd(16)+"Status".padEnd(15)+"Nodes".padEnd(8)}Ver`),console.log(" ".padEnd(134,"-"));for(const o of n){const s=o.uuid?e.cyan(o.uuid):e.gray("-"),d=o.uuid?s+" ".repeat(4):s+" ".repeat(39);console.log(` ${d}${o.name.padEnd(20)}${o.project.padEnd(20)}${o.source.padEnd(16)}${o.status.padEnd(15)}${String(o.nodes).padEnd(8)}${String(o.version)}`)}console.log(" ".padEnd(134,"-")),console.log(`
17
+ Total: ${n.length} workflow${n.length===1?"":"s"}
18
+ `),console.log(" Commands:"),console.log(" zibby start <name> Test locally"),console.log(" zibby deploy <name> Deploy to cloud (generates UUID)"),console.log(" zibby logs <uuid> View remote workflow logs"),t||console.log(`
19
+ Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{B as listAllWorkflowsCommand,D as listLocalWorkflowsCommand};
@@ -1,21 +1,30 @@
1
- import o from"chalk";import{getSessionToken as k}from"../../config/config.js";import h from"dotenv";h.config();const w="https://logs.workflows.zibby.app";function j(e){const r=e.apiKey||process.env.ZIBBY_API_KEY||k();r||(console.log(o.red(`
1
+ import o from"chalk";import{readFileSync as k,existsSync as h}from"fs";import{homedir as x}from"os";import{join as j}from"path";const b="https://logs.workflows.zibby.app";function S(n){const r=j(x(),".zibby","config.json");h(r)||(console.log(o.red(`
2
2
  Not authenticated`)),console.log(o.gray(` Run: zibby login
3
- `)),process.exit(1));const t=e.project||process.env.ZIBBY_PROJECT_ID;return t||(console.log(o.red(`
4
- --project or ZIBBY_PROJECT_ID is required`)),console.log(o.gray(` Example: zibby logs <jobId> --project <id>
5
- `)),process.exit(1)),{token:r,projectId:t}}function $(e){return new Date(e).toISOString().replace("T"," ").replace("Z","")}function I(e){return e==="running"?o.yellow(e):e==="completed"?o.green(e):o.red(e||"unknown")}function b(e){return e?.length>16?e.slice(0,16):e}async function p(e,r){const t=await fetch(e,{headers:{Authorization:`Bearer ${r}`}});if(!t.ok){const i=await t.text();throw new Error(`API ${t.status}: ${i}`)}return t.json()}async function x(e,r,t,i){if(e)return e;const g=r.workflow;g||(console.log(o.red(`
6
- Job ID or --workflow is required`)),console.log(o.gray(" Usage: zibby logs <jobId> --project <id>")),console.log(o.gray(" zibby logs --workflow ticket-triage --project <id>")),console.log(o.gray(` zibby logs --workflow ticket-triage --all --project <id>
7
- `)),process.exit(1));const m=new URLSearchParams({workflow:g,limit:"10"}),{jobs:l}=await p(`${w}/jobs/${i}?${m}`,t);(!l||l.length===0)&&(console.log(o.yellow(`
8
- No jobs found for workflow "${g}".`)),process.exit(0)),console.log(o.gray(`
9
- Recent runs for ${o.cyan(g)}:
10
- `));for(const f of l.slice(0,5))console.log(o.gray(` ${b(f.jobId)} ${I(f.status)} ${f.createdAt||""}`));const a=l[0];return console.log(o.gray(`
11
- Tailing latest: ${o.cyan(b(a.jobId))}
12
- `)),a.jobId}async function T({token:e,projectId:r,jobId:t,follow:i,limit:g}){const m=`${w}/logs/${r}/${t}`;let l=null,a=0;const f=new Set;for(console.log(o.gray(` Tailing logs for job ${o.cyan(b(t))}...`)),console.log(i?o.gray(` Press Ctrl+C to stop.
13
- `):"");;)try{const u=new URLSearchParams({limit:String(g)});l&&u.set("nextToken",l);const n=await p(`${m}?${u}`,e);n.message&&n.lines?.length===0&&a===0&&console.log(o.gray(` ${n.message}`));for(const s of n.lines||[]){const d=`${s.timestamp}:${s.message}`;if(f.has(d))continue;f.add(d);const y=o.gray($(s.timestamp));console.log(`${y} ${s.message.replace(/\n$/,"")}`)}if(a=n.lines?.length>0?0:a+1,l=n.nextForwardToken||null,n.status==="completed"||n.status==="failed"){const s=n.status==="completed"?o.green:o.red;console.log(s(`
14
- Job ${n.status}.`)),process.exit(n.status==="completed"?0:1)}if(!i){n.status&&console.log(o.gray(`
15
- Status: ${n.status}`));break}await new Promise(s=>setTimeout(s,a>5?5e3:2e3))}catch(u){if(u.name==="AbortError")break;console.error(o.red(` Error: ${u.message}`)),i||process.exit(1),await new Promise(n=>setTimeout(n,3e3))}}async function P({token:e,projectId:r,workflow:t,follow:i,limit:g}){const m=`${w}/all/${r}`;let l=null,a=0;const f=new Set;let u=null;for(console.log(o.gray(`
16
- Tailing all runs for ${o.cyan(t)}...`)),console.log(i?o.gray(` Press Ctrl+C to stop.
17
- `):"");;)try{const n=new URLSearchParams({workflow:t,limit:String(g)});l&&n.set("nextToken",l);const c=await p(`${m}?${n}`,e);c.message&&c.lines?.length===0&&a===0&&console.log(o.gray(` ${c.message}`));for(const s of c.lines||[]){const d=`${s.timestamp}:${s.jobId}:${s.message}`;if(f.has(d))continue;f.add(d),s.jobId!==u&&(u!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 ${b(s.jobId)} \u2500\u2500`)),u=s.jobId);const y=o.gray($(s.timestamp));console.log(`${y} ${s.message.replace(/\n$/,"")}`)}if(a=c.lines?.length>0?0:a+1,l=c.nextToken||null,!i){l&&console.log(o.gray(`
18
- ... more logs available. Run again or use --follow to stream.`)),c.jobCount&&console.log(o.gray(` ${c.jobCount} job(s) found.`));break}if(!c.hasRunning&&!l&&a>2){console.log(o.gray(`
19
- No running jobs. All caught up.`));break}await new Promise(s=>setTimeout(s,a>5?5e3:2e3))}catch(n){if(n.name==="AbortError")break;console.error(o.red(` Error: ${n.message}`)),i||process.exit(1),await new Promise(c=>setTimeout(c,3e3))}}async function C(e,r){const{token:t,projectId:i}=j(r),g=r.follow!==!1,m=r.lines?parseInt(r.lines,10):200;if(r.all){const a=r.workflow;return a||(console.log(o.red(`
3
+ `)),process.exit(1));let t;try{t=JSON.parse(k(r,"utf-8"))}catch{console.log(o.red(`
4
+ Config file corrupt`)),console.log(o.gray(` Run: zibby login
5
+ `)),process.exit(1)}const l=t.sessionToken;l||(console.log(o.red(`
6
+ Not authenticated`)),console.log(o.gray(` Run: zibby login
7
+ `)),process.exit(1));const c=n.project;return{token:l,projectId:c}}function p(n){return new Date(n).toISOString().replace("T"," ").replace("Z","")}function T(n){return n==="running"?o.yellow(n):n==="completed"?o.green(n):o.red(n||"unknown")}function d(n){return n?.length>16?n.slice(0,16):n}async function $(n,r){const t=await fetch(n,{headers:{Authorization:`Bearer ${r}`}});if(!t.ok){const l=await t.text();throw new Error(`API ${t.status}: ${l}`)}return t.json()}async function I(n,r,t,l){if(n)return n;l||(console.log(o.red(`
8
+ Job ID or --project is required`)),console.log(o.gray(" Usage: zibby logs <uuid>")),console.log(o.gray(` zibby logs --workflow ticket-triage --project <id>
9
+ `)),process.exit(1));const c=r.workflow;c||(console.log(o.red(`
10
+ Job ID or --workflow is required`)),console.log(o.gray(" Usage: zibby logs <uuid>")),console.log(o.gray(" zibby logs --workflow ticket-triage --project <id>")),console.log(o.gray(` zibby logs --workflow ticket-triage --all --project <id>
11
+ `)),process.exit(1));const y=new URLSearchParams({workflow:c,limit:"10"}),{jobs:a}=await $(`${b}/jobs/${l}?${y}`,t);(!a||a.length===0)&&(console.log(o.yellow(`
12
+ No jobs found for workflow "${c}".`)),process.exit(0)),console.log(o.gray(`
13
+ Recent runs for ${o.cyan(c)}:
14
+ `));for(const f of a.slice(0,5))console.log(o.gray(` ${d(f.jobId)} ${T(f.status)} ${f.createdAt||""}`));const i=a[0];return console.log(o.gray(`
15
+ Tailing latest: ${o.cyan(d(i.jobId))}
16
+ `)),i.jobId}async function P({token:n,projectId:r,workflowUuid:t,follow:l,limit:c}){console.log(o.gray(` Tailing all executions for workflow ${o.cyan(t)}...`)),console.log(o.gray(" Showing live logs from all runs (interleaved by timestamp).")),console.log(o.gray(` Press Ctrl+C to stop.
17
+ `));const y=new Set,a=new Set;let i=null;for(;;)try{const f=r?`${b}/logs/${r}/${t}`:`${b}/job/${t}`,m=new URLSearchParams({limit:String(c)}),s=await $(`${f}?${m}`,n);if(s.executions)for(const e of s.executions)a.has(e.jobId)||(a.size>0&&console.log(o.yellow(`
18
+ \u26A1 New execution: ${d(e.jobId)}
19
+ `)),a.add(e.jobId));const g=[];for(const e of s.lines||[]){const u=`${e.jobId}:${e.timestamp}:${e.message}`;y.has(u)||(y.add(u),g.push(e))}g.sort((e,u)=>e.timestamp-u.timestamp);for(const e of g){const u=e.jobId||e.executionId;u!==i&&(i!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 Execution: ${d(u)} \u2500\u2500`)),i=u);const w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(!l)break;await new Promise(e=>setTimeout(e,2e3))}catch(f){if(f.name==="AbortError")break;console.error(o.red(` Error: ${f.message}`)),l||process.exit(1),await new Promise(m=>setTimeout(m,3e3))}}async function z({token:n,projectId:r,jobId:t,follow:l,limit:c}){const y=r?`${b}/logs/${r}/${t}`:`${b}/job/${t}`;let a=null,i=0;const f=new Set;for(console.log(o.gray(` Tailing logs for job ${o.cyan(t)}...`)),console.log(l?o.gray(` Press Ctrl+C to stop.
20
+ `):"");;)try{const m=new URLSearchParams({limit:String(c)});a&&m.set("nextToken",a);const s=await $(`${y}?${m}`,n);s.message&&s.lines?.length===0&&i===0&&console.log(o.gray(` ${s.message}`)),s.status==="starting"&&s.lines?.length===0&&i===0&&console.log(o.gray(" Container starting..."));for(const e of s.lines||[]){const u=`${e.timestamp}:${e.message}`;if(f.has(u))continue;f.add(u);const w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(i=s.lines?.length>0?0:i+1,a=s.nextForwardToken||null,s.status==="completed"||s.status==="failed"){const e=s.status==="completed"?o.green:o.red;console.log(e(`
21
+ Job ${s.status}.`)),process.exit(s.status==="completed"?0:1)}if(!l){s.status&&console.log(o.gray(`
22
+ Status: ${s.status}`));break}await new Promise(e=>setTimeout(e,i>5?5e3:2e3))}catch(m){if(m.name==="AbortError")break;console.error(o.red(` Error: ${m.message}`)),l||process.exit(1),await new Promise(s=>setTimeout(s,3e3))}}async function E({token:n,projectId:r,workflow:t,follow:l,limit:c}){const y=`${b}/all/${r}`;let a=null,i=0;const f=new Set;let m=null;for(console.log(o.gray(`
23
+ Tailing all runs for ${o.cyan(t)}...`)),console.log(l?o.gray(` Press Ctrl+C to stop.
24
+ `):"");;)try{const s=new URLSearchParams({workflow:t,limit:String(c)});a&&s.set("nextToken",a);const g=await $(`${y}?${s}`,n);g.message&&g.lines?.length===0&&i===0&&console.log(o.gray(` ${g.message}`));for(const e of g.lines||[]){const u=`${e.timestamp}:${e.jobId}:${e.message}`;if(f.has(u))continue;f.add(u),e.jobId!==m&&(m!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 ${d(e.jobId)} \u2500\u2500`)),m=e.jobId);const w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(i=g.lines?.length>0?0:i+1,a=g.nextToken||null,!l){a&&console.log(o.gray(`
25
+ ... more logs available. Run again or use --follow to stream.`)),g.jobCount&&console.log(o.gray(` ${g.jobCount} job(s) found.`));break}if(!g.hasRunning&&!a&&i>2){console.log(o.gray(`
26
+ No running jobs. All caught up.`));break}await new Promise(e=>setTimeout(e,i>5?5e3:2e3))}catch(s){if(s.name==="AbortError")break;console.error(o.red(` Error: ${s.message}`)),l||process.exit(1),await new Promise(g=>setTimeout(g,3e3))}}async function U(n,r){const{token:t,projectId:l}=S(r),c=r.follow!==!1,y=r.lines?parseInt(r.lines,10):500;if(r.all){const i=r.workflow;return i||(console.log(o.red(`
20
27
  --workflow is required with --all`)),console.log(o.gray(` Example: zibby logs --workflow ticket-triage --all --project <id>
21
- `)),process.exit(1)),P({token:t,projectId:i,workflow:a,follow:g,limit:m})}const l=await x(e,r,t,i);return T({token:t,projectId:i,jobId:l,follow:g,limit:m})}export{C as logsCommand};
28
+ `)),process.exit(1)),E({token:t,projectId:l,workflow:i,follow:c,limit:y})}if(r.tailLatest)return n||(console.log(o.red(`
29
+ Workflow UUID is required with --tail-latest`)),console.log(o.gray(` Example: zibby logs <workflowUuid> -t
30
+ `)),process.exit(1)),P({token:t,projectId:l,workflowUuid:n,follow:c,limit:y});const a=await I(n,r,t,l);return z({token:t,projectId:l,jobId:a,follow:c,limit:y})}export{U as logsCommand};
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import{mkdirSync as S,writeFileSync as C,existsSync as k}from"fs";import{join as w,dirname as b,resolve as W}from"path";import{pathToFileURL as j}from"url";const $=process.env.WORKSPACE||"/workspace";async function F(){const s=process.env.WORKFLOW_SOURCES_URL;if(!s)throw new Error("WORKFLOW_SOURCES_URL env var is required");console.log("\u{1F4E6} Fetching workflow sources via pre-signed URL\u2026");const o=await fetch(s);if(!o.ok)throw new Error(`Failed to fetch sources: ${o.status} ${o.statusText}`);const e=await o.json();if(!e.sources||typeof e.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return e}function L(s,o){const e=W(o);let t=0;for(const[r,c]of Object.entries(s)){const n=W(o,r);if(!n.startsWith(`${e}/`)&&n!==e){console.error(` \u26D4 Skipping unsafe path: ${r}`);continue}S(b(n),{recursive:!0}),C(n,c,"utf-8"),t++}return t}async function P(s,o){const e=w(s,"graph.mjs");if(!k(e))throw new Error(`graph.mjs not found at ${e}`);const t=await import(j(e).href),r=o?.entryClass,c=r&&t[r]||t.default||Object.values(t).find(n=>typeof n=="function"&&n.prototype?.buildGraph);if(!c)throw new Error("No WorkflowAgent class found in graph.mjs");return c}async function K(){const{WORKFLOW_JOB_ID:s,WORKFLOW_TYPE:o,PROJECT_ID:e,AGENT_TYPE:t,MODEL:r}=process.env;o||(console.error("\u274C Missing WORKFLOW_TYPE env var"),process.exit(1)),console.log(`
3
- \u{1F680} Zibby Custom Workflow Runner`),console.log(` Job: ${s||"local"}`),console.log(` Workflow: ${o}`),console.log(` Project: ${e||"none"}`),console.log(` Agent: ${t||"default"}`),console.log(` Model: ${r||"auto"}`),console.log("\u2500".repeat(60));const c=await F(),{sources:n,input:O,workflowType:l,version:y}=c;console.log(` Workflow v${y||"?"} \u2014 ${Object.keys(n).length} source files`);const a=w($,".zibby","workflows",l||o),R=L(n,a);console.log(` \u2705 Wrote ${R} files to ${a}`);let p={};const d=w(a,"workflow.json");if(k(d)){const{readFileSync:f}=await import("fs");p=JSON.parse(f(d,"utf-8"))}const g=await P(a,p);console.log(` \u2705 Loaded ${g.name}`);const v=Date.now(),i=new g({workflow:l||o}),h=i.buildGraph(),E={input:O||{},cwd:$,runId:s||`run-${Date.now()}`};console.log(`
2
+ import{mkdirSync as v,writeFileSync as C,existsSync as E}from"fs";import{join as p,dirname as L,resolve as R}from"path";import{pathToFileURL as U}from"url";import{reportFinalStatus as b}from"../../../utils/progress-reporter.js";const S=process.env.WORKSPACE||"/workspace";async function F(){const t=process.env.WORKFLOW_SOURCES_URL;if(!t)throw new Error("WORKFLOW_SOURCES_URL env var is required");console.log("\u{1F4E6} Fetching workflow sources via pre-signed URL\u2026");const o=await fetch(t);if(!o.ok)throw new Error(`Failed to fetch sources: ${o.status} ${o.statusText}`);const e=await o.json();if(!e.sources||typeof e.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return e}function D(t,o){const e=R(o);let n=0;for(const[a,c]of Object.entries(t)){const s=R(o,a);if(!s.startsWith(`${e}/`)&&s!==e){console.error(` \u26D4 Skipping unsafe path: ${a}`);continue}v(L(s),{recursive:!0}),C(s,c,"utf-8"),n++}return n}async function I(t,o){const e=p(t,"graph.mjs");if(!E(e))throw new Error(`graph.mjs not found at ${e}`);const n=await import(U(e).href),a=o?.entryClass,c=a&&n[a]||n.default||Object.values(n).find(s=>typeof s=="function"&&s.prototype?.buildGraph);if(!c)throw new Error("No WorkflowAgent class found in graph.mjs");return c}async function K(){if(!process.env.NODE_PATH){process.env.NODE_PATH="/opt/zibby/packages";const r=await import("module");r.default._initPaths&&r.default._initPaths()}const{WORKFLOW_JOB_ID:t,WORKFLOW_TYPE:o,PROJECT_ID:e,AGENT_TYPE:n,MODEL:a}=process.env;o||(console.error("\u274C Missing WORKFLOW_TYPE env var"),process.exit(1)),console.log(`
3
+ \u{1F680} Zibby Custom Workflow Runner`),console.log(` Job: ${t||"local"}`),console.log(` Workflow: ${o}`),console.log(` Project: ${e||"none"}`),console.log(` Agent: ${n||"default"}`),console.log(` Model: ${a||"auto"}`),console.log("\u2500".repeat(60));const c=await F(),{sources:s,input:_,workflowType:l,version:W}=c;console.log(` Workflow v${W||"?"} \u2014 ${Object.keys(s).length} source files`);const i=p(S,".zibby","workflows",l||o),k=D(s,i);console.log(` \u2705 Wrote ${k} files to ${i}`),console.log(" \u{1F4E6} Installing dependencies...");const{execSync:y}=await import("child_process");try{y("npm install --silent --no-audit --no-fund",{cwd:i,stdio:"inherit"}),console.log(" \u2705 Dependencies installed")}catch(r){console.warn(` \u26A0\uFE0F npm install failed: ${r.message}`)}let d={};const g=p(i,"workflow.json");if(E(g)){const{readFileSync:r}=await import("fs");d=JSON.parse(r(g,"utf-8"))}const m=await I(i,d);console.log(` \u2705 Loaded ${m.name}`);const $=Date.now(),f=new m({workflow:l||o}),h=f.buildGraph(),P={input:_||{},cwd:S,runId:t||`run-${Date.now()}`};console.log(`
4
4
  \u25B6 Running graph (${h.nodes?.size||"?"} nodes)\u2026
5
- `);let u;try{u=await h.run(i,E)}catch(f){console.error(`
6
- \u274C Workflow execution failed: ${f.message}`),console.error(f.stack),process.exit(1)}const m=((Date.now()-v)/1e3).toFixed(1);u?.success!==!1?console.log(`
7
- \u2705 Workflow "${l||o}" completed in ${m}s`):(console.error(`
8
- \u274C Workflow "${l||o}" failed after ${m}s`),process.exit(1)),i.onComplete&&await i.onComplete(u)}export{K as runWorkflowCommand};
5
+ `);let u;try{u=await h.run(f,P)}catch(r){console.error(`
6
+ \u274C Workflow execution failed: ${r.message}`),console.error(r.stack),await w("failed",r.message),process.exit(1)}const O=((Date.now()-$)/1e3).toFixed(1);u?.success!==!1?(console.log(`
7
+ \u2705 Workflow "${l||o}" completed in ${O}s`),await w("completed")):(console.error(`
8
+ \u274C Workflow "${l||o}" failed after ${O}s`),await w("failed",u?.error||"Workflow execution failed"),process.exit(1)),f.onComplete&&await f.onComplete(u)}async function w(t,o=null){const e={EXECUTION_ID:process.env.WORKFLOW_JOB_ID,PROGRESS_API_URL:process.env.PROGRESS_API_URL,PROGRESS_QUEUE_URL:process.env.PROGRESS_QUEUE_URL};if(e.EXECUTION_ID)try{await b(e,{status:t,...o&&{error:o}})}catch(n){console.error(`\u26A0\uFE0F Failed to report status: ${n.message}`)}}export{K as runWorkflowCommand};
@@ -0,0 +1,10 @@
1
+ import f from"ora";import u from"dotenv";import{select as d}from"@inquirer/prompts";import{getApiUrl as p}from"../../config/environments.js";u.config();async function y(l){const s=p(),r=f("Fetching projects...").start();try{const e=await fetch(`${s}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`}});e.ok||(r.fail("Failed to fetch projects"),process.exit(1));let o=await e.json();Array.isArray(o)||(o.projects?o=o.projects:o.data&&(o=o.data)),(!o||o.length===0)&&(r.fail("No projects found"),process.exit(1)),r.succeed(`Found ${o.length} project${o.length===1?"":"s"}`),console.log("");const n=o.map(t=>({name:`${t.name||"Unnamed"} (${t.projectId||t.id})`,value:t.projectId||t.id}));return await d({message:"Select a project:",choices:n})}catch(e){r.fail(`Error: ${e.message}`),process.exit(1)}}async function $(l,s){const r=p(),e=f("Fetching deployed workflows...").start();try{const o=["analysis","implementation","run_test"],n=[];for(const c of o){const a=await fetch(`${r}/projects/${l}/workflows/${c}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`}});if(a.ok){const i=await a.json();i.graph&&n.push({name:c,version:i.version||0,isDefault:i.isDefault!==!1})}}n.length===0&&(e.fail("No deployed workflows found for this project"),process.exit(1)),e.succeed(`Found ${n.length} deployed workflow${n.length===1?"":"s"}`),console.log("");const t=n.map(c=>({name:`${c.name} (v${c.version})${c.isDefault?" [default]":""}`,value:c.name}));return await d({message:"Select a workflow to trigger:",choices:t})}catch(o){e.fail(`Error: ${o.message}`),process.exit(1)}}async function I(l,s={}){const r=s.apiKey||process.env.ZIBBY_API_KEY;r||(console.log(`
2
+ Error: ZIBBY_API_KEY not set`),console.log(` Add to .env or use --api-key flag
3
+ `),process.exit(1));let e=s.project||process.env.ZIBBY_PROJECT_ID;e||(console.log(""),e=await y(r)),l||(console.log(""),l=await $(e,r));let o={};if(s.input)try{o=JSON.parse(s.input)}catch(t){console.log(`
4
+ Error: Invalid JSON in --input`),console.log(` ${t.message}
5
+ `),process.exit(1)}console.log(`
6
+ Triggering Workflow
7
+ `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${l}`),console.log(` Project: ${e}`),Object.keys(o).length>0&&console.log(` Input: ${JSON.stringify(o).substring(0,50)}...`),s.idempotencyKey&&console.log(` Idempotency: ${s.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");const n=f("Triggering workflow execution...").start();try{const t=p(),c={input:o};s.idempotencyKey&&(c.idempotencyKey=s.idempotencyKey);const a=await fetch(`${t}/projects/${e}/workflows/${l}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`},body:JSON.stringify(c)});if(!a.ok){const g=await a.json().catch(()=>({}));a.status===429&&(n.fail("Quota exceeded"),console.log(`
8
+ 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)),n.fail("Trigger failed"),console.log(` Error: ${g.message||a.statusText}
9
+ `),process.exit(1)}const i=await a.json();n.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${i.jobId}`),console.log(` Status: ${i.status}`),console.log(` Version: ${i.version}`),console.log(` Triggered: ${new Date(i.triggeredAt).toLocaleString()}`),console.log(""),console.log(" Monitor execution:"),console.log(` zibby logs ${i.jobId}`),console.log(` zibby logs --workflow ${l}`),console.log("")}catch(t){n.fail("Trigger failed"),console.log(` Error: ${t.message}
10
+ `),process.exit(1)}}export{I as triggerWorkflowCommand};
@@ -0,0 +1 @@
1
+ import{existsSync as t}from"fs";import{join as n}from"path";import{pathToFileURL as e}from"url";async function s(i){const r=n(i,".zibby.config.mjs");if(!t(r))throw new Error(".zibby.config.mjs not found");try{const o=await import(e(r).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}export{s as loadUserConfig};
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {