@zibby/cli 0.1.78 → 0.1.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/zibby.js 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 p}from"commander";import{initCommand as l}from"../commands/init.js";import{runCommand as m}from"../commands/run.js";import{videoCommand as u}from"../commands/video.js";import{uploadCommand as f}from"../commands/upload.js";import{ciSetupCommand as w}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as y,setupCiCommand as g,testWithVideoCommand as k}from"../commands/setup-scripts.js";import{readFileSync as h}from"fs";import{fileURLToPath as b}from"url";import{dirname as v,join as C}from"path";import{bootstrapAgentEnv as I}from"../utils/agent-credentials.js";const P=b(import.meta.url),S=v(P),s=JSON.parse(h(C(S,"../package.json"),"utf-8")),c=`zibby v${s.version}`,i=process.argv.slice(2),j=i.includes("-h")||i.includes("--help"),_=i.includes("-v")||i.includes("-V")||i.includes("--version");_&&(console.log(c),process.exit(0));const d=i[0],D=i[1],A=["logs","uninstall"],B=d==="workflow"&&D==="list";!A.includes(d)&&!B&&console.log(`${c}
3
- `),I(process.cwd());const E=i[0]==="chat",x=["--verbose","--agent","--stream","-s"],Z=i.length>0&&i.every(o=>x.includes(o)||i[i.indexOf(o)-1]==="--agent"),O=i.length===0||E||Z;if(O&&!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(s.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(l),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(u),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(f),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(w),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 y({...o,viewport:t})}),e.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(g),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(k),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 Y=e.command("g").description("Generate scaffolds");Y.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("Fetch and display logs from a workflow execution (use -t to stream in real-time)").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (fetches the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --follow","Stream logs in real-time (like Heroku logs -t)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").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 r=e.command("workflow").description("Manage workflow graphs (download, upload, list)");r.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)}),r.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)}),r.command("delete <uuid>").description("Delete a deployed workflow by UUID").action(async o=>{const{deleteWorkflowCommand:t}=await import("../commands/workflows/delete.js");return t(o,{})});const R=e.command("project").description("Manage Zibby projects");R.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();
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 l}from"commander";import{initCommand as m}from"../commands/init.js";import{runCommand as u}from"../commands/run.js";import{videoCommand as f}from"../commands/video.js";import{uploadCommand as w}from"../commands/upload.js";import{ciSetupCommand as y}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as g,setupCiCommand as h,testWithVideoCommand as k}from"../commands/setup-scripts.js";import{readFileSync as b}from"fs";import{fileURLToPath as v}from"url";import{dirname as I,join as C}from"path";import{bootstrapAgentEnv as P}from"../utils/agent-credentials.js";const S=v(import.meta.url),j=I(S),s=JSON.parse(b(C(j,"../package.json"),"utf-8"));function _(o,e){return e.push(o),e}const c=`zibby v${s.version}`,i=process.argv.slice(2),D=i.includes("-h")||i.includes("--help"),A=i.includes("-v")||i.includes("-V")||i.includes("--version");A&&(console.log(c),process.exit(0));const d=i[0],E=i[1],x=["logs","uninstall"],B=d==="workflow"&&E==="list";!x.includes(d)&&!B&&console.log(`${c}
3
+ `),P(process.cwd());const Z=i[0]==="chat",O=["--verbose","--agent","--stream","-s"],Y=i.length>0&&i.every(o=>O.includes(o)||i[i.indexOf(o)-1]==="--agent"),R=i.length===0||Z||Y;if(R&&!D){const o={},e=i.indexOf("--agent");e!==-1&&i[e+1]&&(o.agent=i[e+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 t=new l;t.name("zibby").description("Zibby Test Automation - AI-powered test generation").version(s.version,"-V, --version"),t.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(m),t.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,e)=>(e.debug?process.env.ZIBBY_DEBUG="true":e.verbose&&(process.env.ZIBBY_VERBOSE="true"),u(o,e))),t.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...o)=>{const{implementCommand:e}=await import("../commands/implement.js");return e(...o)}),t.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:e}=await import("../commands/analyze-graph.js");return e(...o)}),t.command("video").description("Organize test videos next to test files").action(f),t.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(w),t.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)}),t.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)}),t.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async o=>{const{showLoginStatus:e}=await import("../auth/cli-login.js");await e(o),process.exit(0)}),t.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:o}=await import("../commands/list-projects.js");await o()}),t.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(y),t.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 e={width:parseInt(o.viewportWidth,10)||1280,height:parseInt(o.viewportHeight,10)||720};return g({...o,viewport:e})}),t.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(h),t.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(k),t.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:e}=await import("../commands/generate.js");return e(o)}),t.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:e}=await import("../commands/studio.js");return e(o)});const z=t.command("g").description("Generate scaffolds");z.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").action(async o=>{const{generateWorkflowCommand:e}=await import("../commands/workflows/generate.js");return e(o)}),t.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,e)=>{const{startWorkflowCommand:n}=await import("../commands/workflows/start.js");return n(o,e)}),t.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)").option("--dedicated-ip <action>","Manage dedicated egress IP addon: enable | status | disable | use | unuse").action(async(o,e)=>{if(e.dedicatedIp){const{dedicatedEgressCommand:p}=await import("../commands/workflows/dedicated-egress.js");return p(e.dedicatedIp,e.project)}const{deployWorkflowCommand:n}=await import("../commands/workflows/deploy.js");return n(o,e)}),t.command("trigger [uuid]").description("Trigger a deployed workflow by UUID (interactive selection if not provided). Get UUIDs from `zibby workflow list`.").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("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",_,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON/YAML file \u2014 lowest precedence").option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").action(async(o,e)=>{const{triggerWorkflowCommand:n}=await import("../commands/workflows/trigger.js");return n(o,e)}),t.command("logs [jobId]").description("Fetch and display logs from a workflow execution (use -t to stream in real-time)").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (fetches the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --follow","Stream logs in real-time (like Heroku logs -t)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(o,e)=>{const{logsCommand:n}=await import("../commands/workflows/logs.js");return n(o,e)}),t.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=t.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:e}=await import("../commands/memory.js");return e(o)}),a.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async o=>{const{memoryResetCommand:e}=await import("../commands/memory.js");return e(o)});const r=t.command("workflow").description("Manage workflow graphs (download, upload, list)");r.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:e}=await import("../commands/workflow.js");return e(o)}),r.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:e}=await import("../commands/workflows/list.js");return e(o)}),r.command("delete <uuid>").description("Delete a deployed workflow by UUID").action(async o=>{const{deleteWorkflowCommand:e}=await import("../commands/workflows/delete.js");return e(o,{})});const W=t.command("project").description("Manage Zibby projects");W.command("list").description("List all projects").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{const{projectListCommand:e}=await import("../commands/project.js");return e(o)});const L=t.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");L.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:e}=await import("../commands/run-capacity-queue-cli.js");await e(o),process.exit(0)}),t.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:e}=await import("../commands/uninstall.js");await e(o),process.exit(0)}),t.parse();
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{dirname as G,join as L,resolve as J}from"path";import{fileURLToPath as b}from"url";import{readFileSync as j,existsSync as B}from"fs";import{compileGraph as Q,validateGraphConfig as z,WorkflowGraph as W}from"@zibby/workflow";import{invokeAgent as q}from"@zibby/core";import{buildAnalysisGraph as H}from"@zibby/core/templates/code-analysis/graph.js";import{analysisStateSchema as X}from"@zibby/core/templates/code-analysis/state.js";import"@zibby/core/templates/register-nodes.js";async function k(r,t){let a=process.env.CONTEXT_PRESIGNED_URL;if(!a)throw new Error("CONTEXT_PRESIGNED_URL env var is required");console.log("\u{1F4E6} Fetching execution context via pre-signed URL");let e=await fetch(a);if(!e.ok)throw new Error(`Failed to fetch execution context: ${e.status}`);let o=await e.json();return console.log(` \u2705 Got ticketContext (${JSON.stringify(o.ticketContext||{}).length} chars)`),o.nodeConfigs&&Object.keys(o.nodeConfigs).length>0&&console.log(` \u2705 Got nodeConfigs (${Object.keys(o.nodeConfigs).length} nodes configured)`),{ticketContext:o.ticketContext||{},nodeConfigs:o.nodeConfigs||{},graphConfig:o.graphConfig||null,repos:o.repos||[]}}import{SQSClient as M,SendMessageCommand as D}from"@aws-sdk/client-sqs";var I=null;function F(){return I||(I=new M({region:process.env.AWS_REGION||"ap-southeast-2"})),I}async function A(r,t,a,e){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:s,PROGRESS_API_URL:d,PROGRESS_QUEUE_URL:l,PROJECT_API_TOKEN:u}=e;if(!o)return;let f={executionId:o,...s&&{sqsAuthToken:s},step:{name:r,status:t,logs:a,timestamp:new Date().toISOString(),...t==="success"&&{completedAt:new Date().toISOString()}},status:t==="failed"?"failed":"running"};try{d?await v(d,o,f,u):l&&await U(l,o,f)}catch(m){console.error(`\u26A0\uFE0F Failed to send progress: ${m.message}`)}}async function N(r,t,a){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:o,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:d,PROJECT_API_TOKEN:l}=r;if(!e||!a)return;let u=JSON.stringify(a).length;console.log(`Sending artifact: ${t} (${(u/1024).toFixed(1)}KB)`);let f={executionId:e,...o&&{sqsAuthToken:o},artifacts:{[t]:a},timestamp:new Date().toISOString()},m=s?"HTTP":d?"SQS":"NONE",i=JSON.stringify(f).length;try{if(s)await v(s,e,f,l);else if(d)await U(d,e,f);else{console.warn(`\u26A0\uFE0F No transport configured for artifact ${t} \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set`);return}console.log(`Artifact ${t} sent via ${m} (payload=${(i/1024).toFixed(1)}KB, value=${(u/1024).toFixed(1)}KB)`)}catch(_){console.error(`Failed to send artifact ${t} via ${m}:`),console.error(` Payload size: ${(i/1024).toFixed(1)}KB, Value size: ${(u/1024).toFixed(1)}KB`),console.error(` Error: ${_.message}`),_.name&&console.error(` Error type: ${_.name}`),_.code&&console.error(` Error code: ${_.code}`),i>256*1024&&console.error(" \u26A0\uFE0F Message exceeds SQS 256KB limit! Consider splitting or compressing.")}}async function P(r,{status:t,error:a}){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:o,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:d,PROJECT_API_TOKEN:l}=r;if(!e)return;let u={executionId:e,...o&&{sqsAuthToken:o},status:t,...a&&{error:a},timestamp:new Date().toISOString()},f=s?"HTTP":d?"SQS":"NONE",m=JSON.stringify(u).length;console.log(`Sending final status: ${t} via ${f} (${(m/1024).toFixed(1)}KB)`);try{if(s)await v(s,e,u,l);else if(d){let i=["completed","failed","insufficient_context","blocked"].includes(t)?"execution_completed":"progress_update";await U(d,e,u,i)}else{console.warn("No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`Final status ${t} sent via ${f}`)}catch(i){console.error(`Failed to send final status (${t}) via ${f}:`),console.error(` Payload: ${(m/1024).toFixed(1)}KB`),console.error(` Error: ${i.message}`),i.name&&console.error(` Error type: ${i.name}`),i.code&&console.error(` Error code: ${i.code}`)}}async function v(r,t,a,e){let o=`${r}/${t}/progress`,s={"Content-Type":"application/json"};e&&(s.Authorization=`Bearer ${e}`);let d=await fetch(o,{method:"POST",headers:s,body:JSON.stringify(a)});if(!d.ok){let l=await d.text();throw new Error(`HTTP ${d.status}: ${l}`)}}async function U(r,t,a,e="progress_update"){let o=JSON.stringify(a),s=(o.length/1024).toFixed(1);o.length>256*1024&&console.error(`\u274C SQS message too large: ${s}KB (limit 256KB) for ${t} [${e}]`),await F().send(new D({QueueUrl:r,MessageBody:o,MessageGroupId:t,MessageAttributes:{executionId:{DataType:"String",StringValue:t},messageType:{DataType:"String",StringValue:e}}}))}import{writeMcpConfig as V}from"@zibby/core/utils/mcp-config-writer.js";var Y=b(import.meta.url),Z=G(Y),ee=JSON.parse(j(L(Z,"../../package.json"),"utf-8")),oe={analyze_ticket:r=>({key:"analysis",value:{raw:r.raw,structured:r.output}}),generate_code:r=>({key:"codeImplementation",value:r.output?.codeImplementation}),generate_test_cases:r=>({key:"tests",value:r.output?.tests}),finalize:r=>({key:"report",value:r.output?.report})};function te(r,t){return async function(e,o,s){let d=Date.now(),l=[],u="",f=console.log,m=process.stdout.write.bind(process.stdout),i=process.stderr.write.bind(process.stderr),_=!1;console.log=(...n)=>{let h=n.map(w=>typeof w=="string"?w:JSON.stringify(w)).join(" ");l.push(h),_=!0,f(...n),_=!1};let S="";process.stdout.write=(n,h,w)=>{if(!_){let g=typeof n=="string"?n:n.toString();S+=g;let $=S.split(`
2
+ import{dirname as G,join as L,resolve as J}from"path";import{fileURLToPath as b}from"url";import{readFileSync as j,existsSync as B}from"fs";import{compileGraph as Q,validateGraphConfig as z,WorkflowGraph as W}from"@zibby/agent-workflow";import{invokeAgent as q}from"@zibby/core";import{buildAnalysisGraph as H}from"@zibby/core/templates/code-analysis/graph.js";import{analysisStateSchema as X}from"@zibby/core/templates/code-analysis/state.js";import"@zibby/core/templates/register-nodes.js";async function k(r,t){let a=process.env.CONTEXT_PRESIGNED_URL;if(!a)throw new Error("CONTEXT_PRESIGNED_URL env var is required");console.log("\u{1F4E6} Fetching execution context via pre-signed URL");let e=await fetch(a);if(!e.ok)throw new Error(`Failed to fetch execution context: ${e.status}`);let o=await e.json();return console.log(` \u2705 Got ticketContext (${JSON.stringify(o.ticketContext||{}).length} chars)`),o.nodeConfigs&&Object.keys(o.nodeConfigs).length>0&&console.log(` \u2705 Got nodeConfigs (${Object.keys(o.nodeConfigs).length} nodes configured)`),{ticketContext:o.ticketContext||{},nodeConfigs:o.nodeConfigs||{},graphConfig:o.graphConfig||null,repos:o.repos||[]}}import{SQSClient as M,SendMessageCommand as D}from"@aws-sdk/client-sqs";var I=null;function F(){return I||(I=new M({region:process.env.AWS_REGION||"ap-southeast-2"})),I}async function A(r,t,a,e){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:s,PROGRESS_API_URL:d,PROGRESS_QUEUE_URL:l,PROJECT_API_TOKEN:u}=e;if(!o)return;let f={executionId:o,...s&&{sqsAuthToken:s},step:{name:r,status:t,logs:a,timestamp:new Date().toISOString(),...t==="success"&&{completedAt:new Date().toISOString()}},status:t==="failed"?"failed":"running"};try{d?await v(d,o,f,u):l&&await U(l,o,f)}catch(m){console.error(`\u26A0\uFE0F Failed to send progress: ${m.message}`)}}async function N(r,t,a){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:o,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:d,PROJECT_API_TOKEN:l}=r;if(!e||!a)return;let u=JSON.stringify(a).length;console.log(`Sending artifact: ${t} (${(u/1024).toFixed(1)}KB)`);let f={executionId:e,...o&&{sqsAuthToken:o},artifacts:{[t]:a},timestamp:new Date().toISOString()},m=s?"HTTP":d?"SQS":"NONE",i=JSON.stringify(f).length;try{if(s)await v(s,e,f,l);else if(d)await U(d,e,f);else{console.warn(`\u26A0\uFE0F No transport configured for artifact ${t} \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set`);return}console.log(`Artifact ${t} sent via ${m} (payload=${(i/1024).toFixed(1)}KB, value=${(u/1024).toFixed(1)}KB)`)}catch(_){console.error(`Failed to send artifact ${t} via ${m}:`),console.error(` Payload size: ${(i/1024).toFixed(1)}KB, Value size: ${(u/1024).toFixed(1)}KB`),console.error(` Error: ${_.message}`),_.name&&console.error(` Error type: ${_.name}`),_.code&&console.error(` Error code: ${_.code}`),i>256*1024&&console.error(" \u26A0\uFE0F Message exceeds SQS 256KB limit! Consider splitting or compressing.")}}async function P(r,{status:t,error:a}){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:o,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:d,PROJECT_API_TOKEN:l}=r;if(!e)return;let u={executionId:e,...o&&{sqsAuthToken:o},status:t,...a&&{error:a},timestamp:new Date().toISOString()},f=s?"HTTP":d?"SQS":"NONE",m=JSON.stringify(u).length;console.log(`Sending final status: ${t} via ${f} (${(m/1024).toFixed(1)}KB)`);try{if(s)await v(s,e,u,l);else if(d){let i=["completed","failed","insufficient_context","blocked"].includes(t)?"execution_completed":"progress_update";await U(d,e,u,i)}else{console.warn("No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`Final status ${t} sent via ${f}`)}catch(i){console.error(`Failed to send final status (${t}) via ${f}:`),console.error(` Payload: ${(m/1024).toFixed(1)}KB`),console.error(` Error: ${i.message}`),i.name&&console.error(` Error type: ${i.name}`),i.code&&console.error(` Error code: ${i.code}`)}}async function v(r,t,a,e){let o=`${r}/${t}/progress`,s={"Content-Type":"application/json"};e&&(s.Authorization=`Bearer ${e}`);let d=await fetch(o,{method:"POST",headers:s,body:JSON.stringify(a)});if(!d.ok){let l=await d.text();throw new Error(`HTTP ${d.status}: ${l}`)}}async function U(r,t,a,e="progress_update"){let o=JSON.stringify(a),s=(o.length/1024).toFixed(1);o.length>256*1024&&console.error(`\u274C SQS message too large: ${s}KB (limit 256KB) for ${t} [${e}]`),await F().send(new D({QueueUrl:r,MessageBody:o,MessageGroupId:t,MessageAttributes:{executionId:{DataType:"String",StringValue:t},messageType:{DataType:"String",StringValue:e}}}))}import{writeMcpConfig as V}from"@zibby/core/utils/mcp-config-writer.js";var Y=b(import.meta.url),Z=G(Y),ee=JSON.parse(j(L(Z,"../../package.json"),"utf-8")),oe={analyze_ticket:r=>({key:"analysis",value:{raw:r.raw,structured:r.output}}),generate_code:r=>({key:"codeImplementation",value:r.output?.codeImplementation}),generate_test_cases:r=>({key:"tests",value:r.output?.tests}),finalize:r=>({key:"report",value:r.output?.report})};function te(r,t){return async function(e,o,s){let d=Date.now(),l=[],u="",f=console.log,m=process.stdout.write.bind(process.stdout),i=process.stderr.write.bind(process.stderr),_=!1;console.log=(...n)=>{let h=n.map(w=>typeof w=="string"?w:JSON.stringify(w)).join(" ");l.push(h),_=!0,f(...n),_=!1};let S="";process.stdout.write=(n,h,w)=>{if(!_){let g=typeof n=="string"?n:n.toString();S+=g;let $=S.split(`
3
3
  `);S=$.pop()||"";for(let y of $){let O=y.trim();O&&l.push(O)}}return m(n,h,w)},f(`[Middleware] Started capturing logs for ${e}`);let R=!1,T=setInterval(()=>{if(R)return;let n=l.join(`
4
4
  `);n!==u&&n.length>0&&(u=n,i(`\u{1F4E1} [Middleware] Sending live update for ${e}: ${n.length} chars, ${l.length} lines
5
5
  `),r(e,"in_progress",n,s).catch(h=>{i(`\u26A0\uFE0F [Middleware] Failed to send live update: ${h.message}
@@ -373,4 +373,4 @@ ${o}/
373
373
 
374
374
  - Documentation: https://docs.zibby.dev
375
375
  - Examples: https://github.com/zibby/examples
376
- `}export{ft as initCommand};
376
+ `}export{je as generateConfig,ft as initCommand};
@@ -1,4 +1,4 @@
1
- import{readFileSync as N,writeFileSync as b,existsSync as B,mkdirSync as D}from"fs";import{resolve as T,join as m}from"path";import o from"chalk";import $ from"ora";import Y from"dotenv";import R from"inquirer";var w={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function _(){let t;if(process.env.ZIBBY_API_URL)t=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";w[e]?t=w[e].apiUrl:t=w.prod.apiUrl}try{let e=new URL(t);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),w.prod.apiUrl):t}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${t}`),w.prod.apiUrl}}function j(){let t=process.env.ZIBBY_ENV||"prod";return w[t]||w.prod}import{validateGraphConfig as z,generateWorkflowCode as S,generateNodeConfigsJson as F}from"@zibby/workflow";import"@zibby/core/templates/register-nodes.js";Y.config();async function L(t){let e=_(),l=$("Fetching projects...").start();try{let c=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});c.ok||(l.fail("Failed to fetch projects"),process.exit(1));let n=await c.json();Array.isArray(n)||(n.projects&&Array.isArray(n.projects)?n=n.projects:n.data&&Array.isArray(n.data)?n=n.data:(l.fail("Unexpected response format"),process.exit(1))),(!n||n.length===0)&&(l.fail("No projects found"),process.exit(1)),l.stop();let i=n.map(r=>({name:`${r.name||"Unnamed"} (${r.id||"no-id"})`,value:r.id})),{projectId:g}=await R.prompt([{type:"list",name:"projectId",message:"Select a project:",choices:i}]);return g}catch(c){l.fail(`Error: ${c.message}`),process.exit(1)}}function x(t){let e=t.apiKey||process.env.ZIBBY_API_KEY;e||(console.log(o.red(`
1
+ import{readFileSync as N,writeFileSync as b,existsSync as B,mkdirSync as D}from"fs";import{resolve as T,join as m}from"path";import o from"chalk";import $ from"ora";import Y from"dotenv";import R from"inquirer";var w={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function _(){let t;if(process.env.ZIBBY_API_URL)t=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";w[e]?t=w[e].apiUrl:t=w.prod.apiUrl}try{let e=new URL(t);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),w.prod.apiUrl):t}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${t}`),w.prod.apiUrl}}function j(){let t=process.env.ZIBBY_ENV||"prod";return w[t]||w.prod}import{validateGraphConfig as z,generateWorkflowCode as S,generateNodeConfigsJson as F}from"@zibby/agent-workflow";import"@zibby/core/templates/register-nodes.js";Y.config();async function L(t){let e=_(),l=$("Fetching projects...").start();try{let c=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});c.ok||(l.fail("Failed to fetch projects"),process.exit(1));let n=await c.json();Array.isArray(n)||(n.projects&&Array.isArray(n.projects)?n=n.projects:n.data&&Array.isArray(n.data)?n=n.data:(l.fail("Unexpected response format"),process.exit(1))),(!n||n.length===0)&&(l.fail("No projects found"),process.exit(1)),l.stop();let i=n.map(r=>({name:`${r.name||"Unnamed"} (${r.id||"no-id"})`,value:r.id})),{projectId:g}=await R.prompt([{type:"list",name:"projectId",message:"Select a project:",choices:i}]);return g}catch(c){l.fail(`Error: ${c.message}`),process.exit(1)}}function x(t){let e=t.apiKey||process.env.ZIBBY_API_KEY;e||(console.log(o.red(`
2
2
  ZIBBY_API_KEY not set`)),console.log(o.gray(` Add to .env: ZIBBY_API_KEY=zby_xxx
3
3
  `)),process.exit(1));let l=t.project||process.env.ZIBBY_PROJECT_ID;return l||(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
@@ -0,0 +1,44 @@
1
+ import g from"ora";import h from"inquirer";import{readFileSync as I,existsSync as E}from"fs";import{join as P}from"path";import{homedir as m}from"os";var p={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function b(){let s;if(process.env.ZIBBY_API_URL)s=process.env.ZIBBY_API_URL;else{let t=process.env.ZIBBY_ENV||"prod";p[t]?s=p[t].apiUrl:s=p.prod.apiUrl}try{let t=new URL(s);return t.protocol!=="http:"&&t.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${t.protocol} (only http/https allowed)`),p.prod.apiUrl):s}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${s}`),p.prod.apiUrl}}function y(){let s=P(m(),".zibby","config.json");if(E(s))try{let n=JSON.parse(I(s,"utf-8"));if(n.sessionToken)return n.sessionToken}catch{}let t=process.env.ZIBBY_API_KEY;if(t)return t;console.log(`
2
+ Not authenticated`),console.log(" Run: zibby login"),console.log(` OR set ZIBBY_API_KEY env var
3
+ `),process.exit(1)}async function L(s,t){let n=y(),e=b(),o={"Content-Type":"application/json",Authorization:`Bearer ${n}`};switch(s){case"enable":return $(e,o);case"status":return v(e,o);case"disable":return w(e,o);case"use":case"unuse":return U(e,o,s,t);default:console.log(`
4
+ Error: Unknown action "${s}"`),console.log(` Valid actions: enable | status | disable | use | unuse
5
+ `),process.exit(1)}}async function $(s,t){console.log(`
6
+ Dedicated Egress IP \u2014 Enable
7
+ `);let n=g("Checking account...").start(),e;try{let c=await fetch(`${s}/addons/dedicated-egress/status`,{method:"GET",headers:t});if(!c.ok){let a=await c.json().catch(()=>({}));n.fail("Check failed"),console.log(` Error: ${a.message||c.statusText}
8
+ `),process.exit(1)}e=await c.json()}catch(c){n.fail("Check failed"),console.log(` Error: ${c.message}
9
+ `),process.exit(1)}if(n.stop(),e.enabled&&!e.cancelAtPeriodEnd){console.log(" Already active."),e.elasticIp&&console.log(` Your static IP: ${e.elasticIp}`),console.log("");return}e.hasProSub||(console.log(" Dedicated egress requires an active Pro subscription."),console.log(` Upgrade at: https://zibby.app/billing
10
+ `),process.exit(1));let o=e.pricing?.priceUSD??50,i=e.pricing?.billingPeriod??"month",r=e.pricing?.description||"Static outbound IP for allowlisting on corporate firewalls.",l=e.enabled&&e.cancelAtPeriodEnd;console.log(` ${r}`),console.log(` Cost: $${o} per ${i} (prorated from today, billed via Stripe)
11
+ `);let{confirm:d}=await h.prompt([{type:"confirm",name:"confirm",message:l?`Re-enable dedicated egress at $${o}/${i}?`:`Enable dedicated egress at $${o}/${i}?`,default:!1}]);if(!d){console.log(`
12
+ Cancelled.
13
+ `);return}let u=g("Requesting dedicated egress IP for your account...").start();try{let c=await fetch(`${s}/addons/dedicated-egress/enable`,{method:"POST",headers:t});if(!c.ok){let f=await c.json().catch(()=>({}));u.fail("Enable failed"),f.code==="PAYMENT_METHOD_REQUIRED"?(console.log(`
14
+ No payment method on file.`),console.log(` Add a card first at: https://zibby.app/billing
15
+ `)):console.log(` Error: ${f.error||f.message||c.statusText}
16
+ `),process.exit(1)}let a=await c.json();u.succeed(l?"Re-enabled":"Provisioning started"),console.log(""),l&&a.elasticIp?console.log(` Your static IP is back online: ${a.elasticIp}
17
+ `):(console.log(` This takes 2-3 minutes.
18
+ `),a.elasticIp&&(console.log(" Once ready, allowlist this IP on your GitLab / GitHub:"),console.log(` ${a.elasticIp}
19
+ `))),console.log(" Then opt each project in:"),console.log(` zibby deploy --dedicated-ip use --project <project-id>
20
+ `),console.log(" Check status:"),console.log(` zibby deploy --dedicated-ip status
21
+ `)}catch(c){u.fail("Enable failed"),console.log(` Error: ${c.message}
22
+ `),process.exit(1)}}async function v(s,t){let n=g("Fetching dedicated egress status...").start();try{let e=await fetch(`${s}/addons/dedicated-egress/status`,{method:"GET",headers:t});if(!e.ok){let r=await e.json().catch(()=>({}));n.fail("Status check failed"),console.log(` Error: ${r.message||e.statusText}
23
+ `),process.exit(1)}let o=await e.json();if(n.stop(),console.log(""),!o.enabled){console.log(` Dedicated egress IP: not enabled
24
+ `),console.log(" Enable it with:"),console.log(` zibby deploy --dedicated-ip enable
25
+ `);return}if(o.status==="provisioning"){console.log(` Dedicated egress IP: provisioning (2-3 min)
26
+ `),o.elasticIp&&console.log(` Your static IP (pending): ${o.elasticIp}`),console.log(""),console.log(" Check again in a moment:"),console.log(` zibby deploy --dedicated-ip status
27
+ `);return}let i=o.provisionedAt?new Date(o.provisionedAt).toLocaleDateString():"unknown";if(console.log(` Dedicated egress IP: active
28
+ `),console.log(` Your static IP: ${o.elasticIp}`),console.log(` Subnet: ${o.subnetId}`),console.log(` Provisioned: ${i}`),o.projects?.length){console.log(`
29
+ Projects using dedicated IP:`);for(let r of o.projects){let l=r.usesDedicatedEgress?"\u2713":"\u2717",d=r.usesDedicatedEgress?"":" [not opted in]";console.log(` ${l} ${r.name||r.projectId}${d}`)}}console.log(""),console.log(" Add this IP to your GitLab allowlist:"),console.log(" GitLab \u2192 Settings \u2192 Network \u2192 Outbound requests \u2192 Allow requests to:"),console.log(` ${o.elasticIp}
30
+ `)}catch(e){n.fail("Status check failed"),console.log(` Error: ${e.message}
31
+ `),process.exit(1)}}async function w(s,t){console.log(`
32
+ Dedicated Egress IP \u2014 Disable
33
+ `);let n=g("Disabling dedicated egress IP for your account...").start();try{let e=await fetch(`${s}/addons/dedicated-egress/disable`,{method:"DELETE",headers:t});if(!e.ok){let o=await e.json().catch(()=>({}));n.fail("Disable failed"),console.log(` Error: ${o.message||e.statusText}
34
+ `),process.exit(1)}n.succeed("Dedicated egress IP disabled"),console.log(""),console.log(" The NAT Gateway and Elastic IP are being released."),console.log(` All your Fargate tasks will now use dynamic public IPs.
35
+ `)}catch(e){n.fail("Disable failed"),console.log(` Error: ${e.message}
36
+ `),process.exit(1)}}async function U(s,t,n,e){e||(e=process.env.ZIBBY_PROJECT_ID),e||(console.log(`
37
+ Error: --project <id> is required for "zibby deploy --dedicated-ip ${n}"`),console.log(` Or set ZIBBY_PROJECT_ID env var
38
+ `),process.exit(1));let o=n==="use",i=g(o?`Opting project ${e} into dedicated egress...`:`Opting project ${e} out of dedicated egress...`).start();try{let r=await fetch(`${s}/projects/${e}/addons/dedicated-egress/use`,{method:o?"POST":"DELETE",headers:t});if(!r.ok){let d=await r.json().catch(()=>({}));i.fail("Failed"),r.status===402?(console.log(`
39
+ Dedicated egress IP is not enabled for your account.`),console.log(" Enable it first:"),console.log(` zibby deploy --dedicated-ip enable
40
+ `)):console.log(` Error: ${d.message||r.statusText}
41
+ `),process.exit(1)}let l=await r.json();o?(i.succeed(`Project will now route through ${l.elasticIp||"dedicated IP"}`),console.log(""),l.elasticIp&&(console.log(` Static IP for this project: ${l.elasticIp}`),console.log(""),console.log(" Make sure this IP is allowlisted on your GitLab / GitHub:"),console.log(` ${l.elasticIp}
42
+ `))):(i.succeed("Project will now use dynamic public IP"),console.log(""),console.log(` This project's Fargate tasks will use a random IP going forward.
43
+ `))}catch(r){i.fail("Failed"),console.log(` Error: ${r.message}
44
+ `),process.exit(1)}}export{L as dedicatedEgressCommand};
@@ -0,0 +1 @@
1
+ function d(n,o){return n?.uuid||n?.workflowUuid||o?.uuid||null}function l({uuid:n,name:o,projectId:i,result:u,existingManifest:e=null,now:t=()=>new Date().toISOString()}){let r=u?.version??(e?.version??0)+1;return{uuid:n,name:o,projectId:i,version:r,deployedAt:t()}}export{l as buildDeployManifest,d as pickCloudUuid};
@@ -1,16 +1,17 @@
1
- import{existsSync as l,readFileSync as z}from"fs";import{join as c}from"path";import p from"chalk";import S from"ora";import Q from"dotenv";import{select as Y}from"@inquirer/prompts";import{existsSync as M}from"fs";import{join as H}from"path";import{pathToFileURL as q}from"url";async function N(e){let s=H(e,".zibby.config.mjs");if(!M(s))throw new Error(".zibby.config.mjs not found");try{let a=await import(q(s).href);return a.default||a}catch(a){throw new Error(`Failed to load .zibby.config.mjs: ${a.message}`,{cause:a})}}var _={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function E(){let e;if(process.env.ZIBBY_API_URL)e=process.env.ZIBBY_API_URL;else{let s=process.env.ZIBBY_ENV||"prod";_[s]?e=_[s].apiUrl:e=_.prod.apiUrl}try{let s=new URL(e);return s.protocol!=="http:"&&s.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${s.protocol} (only http/https allowed)`),_.prod.apiUrl):e}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${e}`),_.prod.apiUrl}}Q.config();async function X(e,s){let a=E(),f=S("Fetching projects...").start();try{let w=s||e,d=await fetch(`${a}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${w}`}});d.ok||(f.fail("Failed to fetch projects"),process.exit(1));let t=await d.json();Array.isArray(t)||(t.projects&&Array.isArray(t.projects)?t=t.projects:t.data&&Array.isArray(t.data)?t=t.data:(f.fail("Unexpected response format"),process.exit(1))),(!t||t.length===0)&&(f.fail("No projects found"),process.exit(1)),f.succeed(`Found ${t.length} project${t.length===1?"":"s"}`),console.log("");let I=t.map(g=>{let U=g.projectId||g.id||g._id||"unknown";return{name:`${g.name||g.projectName||"Unnamed"} (${U})`,value:U}});return await Y({message:"Select a project to deploy to:",choices:I})}catch(w){f.fail(`Error: ${w.message}`),process.exit(1)}}async function ho(e,s={}){let a=process.cwd(),f=null,w=s.apiKey||process.env.ZIBBY_API_KEY;try{let n=c(process.env.HOME||process.env.USERPROFILE,".zibby","config.json");l(n)&&(f=JSON.parse(z(n,"utf-8")).sessionToken)}catch{}!f&&!w&&(console.log(`
1
+ import{existsSync as f,readFileSync as P,writeFileSync as so}from"fs";import{join as i}from"path";import d from"chalk";import V from"ora";import ro from"dotenv";import{select as W}from"@inquirer/prompts";import{existsSync as eo}from"fs";import{join as to}from"path";import{pathToFileURL as no}from"url";async function F(o){let n=to(o,".zibby.config.mjs");if(!eo(n))throw new Error(".zibby.config.mjs not found");try{let c=await import(no(n).href);return c.default||c}catch(c){throw new Error(`Failed to load .zibby.config.mjs: ${c.message}`,{cause:c})}}var v={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function O(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let n=process.env.ZIBBY_ENV||"prod";v[n]?o=v[n].apiUrl:o=v.prod.apiUrl}try{let n=new URL(o);return n.protocol!=="http:"&&n.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${n.protocol} (only http/https allowed)`),v.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),v.prod.apiUrl}}function M(o,n){return o?.uuid||o?.workflowUuid||n?.uuid||null}function J({uuid:o,name:n,projectId:c,result:l,existingManifest:u=null,now:a=()=>new Date().toISOString()}){let e=l?.version??(u?.version??0)+1;return{uuid:o,name:n,projectId:c,version:e,deployedAt:a()}}ro.config();async function io(o,n){let c=O(),l=V("Fetching projects...").start();try{let u=n||o,a=await fetch(`${c}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`}});a.ok||(l.fail("Failed to fetch projects"),process.exit(1));let e=await a.json();Array.isArray(e)||(e.projects&&Array.isArray(e.projects)?e=e.projects:e.data&&Array.isArray(e.data)?e=e.data:(l.fail("Unexpected response format"),process.exit(1))),(!e||e.length===0)&&(l.fail("No projects found"),process.exit(1)),l.succeed(`Found ${e.length} project${e.length===1?"":"s"}`),console.log("");let I=e.map(g=>{let $=g.projectId||g.id||g._id||"unknown";return{name:`${g.name||g.projectName||"Unnamed"} (${$})`,value:$}});return await W({message:"Select a project to deploy to:",choices:I})}catch(u){l.fail(`Error: ${u.message}`),process.exit(1)}}async function vo(o,n={}){let c=process.cwd(),l=null,u=n.apiKey||process.env.ZIBBY_API_KEY;try{let s=i(process.env.HOME||process.env.USERPROFILE,".zibby","config.json");f(s)&&(l=JSON.parse(P(s,"utf-8")).sessionToken)}catch{}!l&&!u&&(console.log(`
2
2
  Error: Not authenticated`),console.log(" Run: zibby login"),console.log(` Or set ZIBBY_API_KEY
3
- `),process.exit(1));let d=".zibby/workflows";try{d=(await N(a))?.paths?.workflows||".zibby/workflows"}catch{}if(!e){let n=c(a,d);l(n)||(console.log(`
4
- Error: No workflows found in ${d}/`),console.log(` Create one with: zibby g workflow <name>
5
- `),process.exit(1));let{readdir:i,stat:m}=await import("fs/promises"),A=await i(n),b=[];for(let j of A){let u=c(n,j);if(!(await m(u)).isDirectory())continue;(l(c(u,"graph.mjs"))||l(c(u,"graph.js")))&&b.push(j)}b.length===0&&(console.log(`
6
- Error: No workflows found in ${d}/`),console.log(` Create one with: zibby g workflow <name>
7
- `),process.exit(1)),console.log(""),e=await Y({message:"Select a workflow to deploy:",choices:b.map(j=>({name:j,value:j}))})}let t=s.project||process.env.ZIBBY_PROJECT_ID;t||(console.log(""),t=await X(w,f));let I=f||w,h=c(a,d,e);l(h)||(console.log(`
8
- Error: Workflow not found: ${d}/${e}`),console.log(` Run: zibby workflow list
9
- `),process.exit(1));let g=c(h,"graph.mjs"),U=c(h,"workflow.json");l(g)||(console.log(`
10
- Error: graph.mjs not found in ${d}/${e}/`),process.exit(1)),console.log(`
3
+ `),process.exit(1));let a=".zibby/workflows";try{a=(await F(c))?.paths?.workflows||".zibby/workflows"}catch{}if(!o){let s=i(c,a);f(s)||(console.log(`
4
+ Error: No workflows found in ${a}/`),console.log(` Create one with: zibby g workflow <name>
5
+ `),process.exit(1));let{readdir:p,stat:m}=await import("fs/promises"),D=await p(s),j=[];for(let k of D){let y=i(s,k);if(!(await m(y)).isDirectory())continue;(f(i(y,"graph.mjs"))||f(i(y,"graph.js")))&&j.push(k)}j.length===0&&(console.log(`
6
+ Error: No workflows found in ${a}/`),console.log(` Create one with: zibby g workflow <name>
7
+ `),process.exit(1)),console.log(""),o=await W({message:"Select a workflow to deploy:",choices:j.map(k=>({name:k,value:k}))})}let e=n.project||process.env.ZIBBY_PROJECT_ID;e||(console.log(""),e=await io(u,l));let I=l||u,h=i(c,a,o);f(h)||(console.log(`
8
+ Error: Workflow not found: ${a}/${o}`),console.log(` Run: zibby workflow list
9
+ `),process.exit(1));let g=i(h,"graph.mjs"),$=i(h,"workflow.json");f(g)||(console.log(`
10
+ Error: graph.mjs not found in ${a}/${o}/`),process.exit(1)),console.log(`
11
11
  Deploying Workflow
12
- `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${e}`),console.log(` Project: ${t}`),console.log(" ".padEnd(60,"-")),console.log("");let r=S("Validating workflow...").start(),B=z(g,"utf-8");if(B.includes("@zibby/core")||B.includes("@zibby/skills")){let n=c(h,"package.json");l(n)||(r.fail("Missing package.json"),console.log(""),console.log(p.red(" \u2717 graph.mjs imports @zibby packages but no package.json found")),console.log(""),console.log(p.yellow(" Create package.json with:")),console.log(""),console.log(p.gray(" {")),console.log(p.gray(' "type": "module",')),console.log(p.gray(' "dependencies": {')),console.log(p.gray(' "@zibby/core": "workspace:*"')),console.log(p.gray(" }")),console.log(p.gray(" }")),console.log(""),process.exit(1));let i=JSON.parse(z(n,"utf-8"));!{...i.dependencies,...i.devDependencies}["@zibby/core"]&&B.includes("@zibby/core")&&(r.fail("Missing @zibby/core dependency"),console.log(""),console.log(p.red(" \u2717 graph.mjs imports @zibby/core but it's not in package.json")),console.log(""),console.log(p.yellow(" Add to package.json dependencies:")),console.log(p.gray(' "@zibby/core": "workspace:*"')),console.log(""),process.exit(1))}r.text="Loading workflow graph...";try{let{pathToFileURL:n}=await import("url"),i=await import(n(g).href),m;if(i.default)if(typeof i.default=="function"){let o=i.default.prototype;o&&o.buildGraph?m=new i.default:m=i.default()}else r.fail("graph.mjs must export a class or factory function"),process.exit(1);else{let o=Object.values(i).find(k=>k.prototype&&k.prototype.buildGraph);o?m=new o:(r.fail("graph.mjs must export a WorkflowAgent class or factory function"),process.exit(1))}let b=m.buildGraph().serialize(),{readdir:j,readFile:u}=await import("fs/promises"),y={};r.text="Packaging workflow sources...";let R=await u(g,"utf-8");if(y["graph.mjs"]=R,l(U)){let o=await u(U,"utf-8");y["workflow.json"]=o}let P=c(h,"nodes");if(l(P)){let o=await j(P);for(let k of o)if(k.endsWith(".mjs")||k.endsWith(".js")){let G=c(P,k),K=await u(G,"utf-8");y[`nodes/${k}`]=K}}let C=c(h,"package.json");if(l(C)){let o=await u(C,"utf-8");y["package.json"]=o,r.text="Including package.json for dependencies..."}let L=c(h,"package-lock.json");if(l(L)){let o=await u(L,"utf-8");y["package-lock.json"]=o}r.text=`Uploading to cloud (${b.nodes.size||Object.keys(b.nodes||{}).length} nodes, ${Object.keys(y).length} files)...`;let T=E(),O=JSON.stringify({format:1,sources:y}),D=Buffer.byteLength(O,"utf8"),v=await fetch(`${T}/projects/${t}/workflows/${e}/sources/presign`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${I}`},body:JSON.stringify({contentLength:D})});if(!v.ok){let o=await v.json().catch(()=>({}));r.fail("Deploy failed (presign)"),console.log(` Error: ${o.error||o.message||v.statusText}
13
- `),process.exit(1)}let Z=await v.json(),{uploadUrl:F,key:V,headers:W}=Z,x=await fetch(F,{method:"PUT",headers:{...W||{},"Content-Length":String(D)},body:O});if(!x.ok){let o=await x.text().catch(()=>"");r.fail("Deploy failed (S3 upload)"),console.log(` S3 PUT failed: ${x.status} ${o.slice(0,200)}
14
- `),process.exit(1)}r.text="Saving workflow definition...";let $=await fetch(`${T}/projects/${t}/workflows/${e}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${I}`},body:JSON.stringify({graph:b,sourcesStagingKey:V,isDefault:!1})});if(!$.ok){let o=await $.json().catch(()=>({}));r.fail("Deploy failed"),console.log(` Error: ${o.message||o.error||$.statusText}
15
- `),process.exit(1)}let J=await $.json();r.succeed(`Deployed successfully (v${J.version||1})`),console.log(""),console.log(" Next steps:"),console.log(` zibby start ${e} Run locally`),console.log(" zibby workflow list View all workflows"),console.log("")}catch(n){r.fail("Deploy failed"),console.log(` Error: ${n.message}
16
- `),process.exit(1)}}export{ho as deployWorkflowCommand};
12
+ `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${o}`),console.log(` Project: ${e}`),console.log(" ".padEnd(60,"-")),console.log("");let r=V("Validating workflow...").start(),z=P(g,"utf-8");if(z.includes("@zibby/core")||z.includes("@zibby/skills")){let s=i(h,"package.json");f(s)||(r.fail("Missing package.json"),console.log(""),console.log(d.red(" \u2717 graph.mjs imports @zibby packages but no package.json found")),console.log(""),console.log(d.yellow(" Create package.json with:")),console.log(""),console.log(d.gray(" {")),console.log(d.gray(' "type": "module",')),console.log(d.gray(' "dependencies": {')),console.log(d.gray(' "@zibby/core": "workspace:*"')),console.log(d.gray(" }")),console.log(d.gray(" }")),console.log(""),process.exit(1));let p=JSON.parse(P(s,"utf-8"));!{...p.dependencies,...p.devDependencies}["@zibby/core"]&&z.includes("@zibby/core")&&(r.fail("Missing @zibby/core dependency"),console.log(""),console.log(d.red(" \u2717 graph.mjs imports @zibby/core but it's not in package.json")),console.log(""),console.log(d.yellow(" Add to package.json dependencies:")),console.log(d.gray(' "@zibby/core": "workspace:*"')),console.log(""),process.exit(1))}r.text="Loading workflow graph...";try{let{pathToFileURL:s}=await import("url"),p=await import(s(g).href),m;if(p.default)if(typeof p.default=="function"){let t=p.default.prototype;t&&t.buildGraph?m=new p.default:m=p.default()}else r.fail("graph.mjs must export a class or factory function"),process.exit(1);else{let t=Object.values(p).find(w=>w.prototype&&w.prototype.buildGraph);t?m=new t:(r.fail("graph.mjs must export a WorkflowAgent class or factory function"),process.exit(1))}let j=m.buildGraph().serialize(),{readdir:k,readFile:y}=await import("fs/promises"),b={};r.text="Packaging workflow sources...";let L=await y(g,"utf-8");if(b["graph.mjs"]=L,f($)){let t=await y($,"utf-8");b["workflow.json"]=t}let A=i(h,"nodes");if(f(A)){let t=await k(A);for(let w of t)if(w.endsWith(".mjs")||w.endsWith(".js")){let X=i(A,w),oo=await y(X,"utf-8");b[`nodes/${w}`]=oo}}let T=i(h,"package.json");if(f(T)){let t=await y(T,"utf-8");b["package.json"]=t,r.text="Including package.json for dependencies..."}let S=i(h,"package-lock.json");if(f(S)){let t=await y(S,"utf-8");b["package-lock.json"]=t}r.text=`Uploading to cloud (${j.nodes.size||Object.keys(j.nodes||{}).length} nodes, ${Object.keys(b).length} files)...`;let N=O(),Y=JSON.stringify({format:1,sources:b}),Z=Buffer.byteLength(Y,"utf8"),_=await fetch(`${N}/projects/${e}/workflows/${o}/sources/presign`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${I}`},body:JSON.stringify({contentLength:Z})});if(!_.ok){let t=await _.json().catch(()=>({}));r.fail("Deploy failed (presign)"),console.log(` Error: ${t.error||t.message||_.statusText}
13
+ `),process.exit(1)}let G=await _.json(),{uploadUrl:K,key:H,headers:q}=G,E=await fetch(K,{method:"PUT",headers:{...q||{},"Content-Length":String(Z)},body:Y});if(!E.ok){let t=await E.text().catch(()=>"");r.fail("Deploy failed (S3 upload)"),console.log(` S3 PUT failed: ${E.status} ${t.slice(0,200)}
14
+ `),process.exit(1)}r.text="Saving workflow definition...";let x=await fetch(`${N}/projects/${e}/workflows/${o}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${I}`},body:JSON.stringify({graph:j,sourcesStagingKey:H,isDefault:!1})});if(!x.ok){let t=await x.json().catch(()=>({}));r.fail("Deploy failed"),console.log(` Error: ${t.message||t.error||x.statusText}
15
+ `),process.exit(1)}let R=await x.json(),B=i(h,".zibby-deploy.json"),C=f(B)?(()=>{try{return JSON.parse(P(B,"utf-8"))}catch{return null}})():null,U=M(R,C);if(U){let t=J({uuid:U,name:o,projectId:e,result:R,existingManifest:C});try{so(B,`${JSON.stringify(t,null,2)}
16
+ `,"utf-8")}catch(w){console.log(` Warning: failed to write ${B}: ${w.message}`)}}let Q=C?"Updated":"Deployed";r.succeed(`${Q} ${o} (v${R.version||1})`),console.log(""),U&&console.log(` UUID: ${U}`),console.log(""),console.log(" Next steps:"),console.log(` zibby start ${o} Run locally`),U&&console.log(` zibby trigger ${U} Run in cloud`),console.log(" zibby workflow list View all workflows"),console.log("")}catch(s){r.fail("Deploy failed"),console.log(` Error: ${s.message}
17
+ `),process.exit(1)}}export{vo as deployWorkflowCommand};
@@ -1,5 +1,88 @@
1
- import{mkdir as d,writeFile as i}from"fs/promises";import{existsSync as b}from"fs";import{join as n}from"path";import o from"chalk";import x from"ora";import{existsSync as h}from"fs";import{join as y}from"path";import{pathToFileURL as w}from"url";async function g(r){let e=y(r,".zibby.config.mjs");if(!h(e))throw new Error(".zibby.config.mjs not found");try{let t=await import(w(e).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}var k=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,f=["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 $(){let r=f[Math.floor(Math.random()*f.length)],e=u[Math.floor(Math.random()*u.length)];return`${r}-${e}`}function j(r){return`${r.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function z(r,e){return`/**
2
- * ${r}
1
+ import{mkdir as f,writeFile as d}from"fs/promises";import{existsSync as y}from"fs";import{join as a}from"path";import t from"chalk";import E from"ora";import{existsSync as x}from"fs";import{join as v}from"path";import{pathToFileURL as I}from"url";async function g(o){let e=v(o,".zibby.config.mjs");if(!x(e))throw new Error(".zibby.config.mjs not found");try{let s=await import(I(e).href);return s.default||s}catch(s){throw new Error(`Failed to load .zibby.config.mjs: ${s.message}`,{cause:s})}}import{mkdir as ee,writeFile as te,readFile as oe}from"fs/promises";import{existsSync as se,readdirSync as ie}from"fs";import{join as re,resolve as le,dirname as A}from"path";import{homedir as de}from"os";import me from"inquirer";import ue from"chalk";import ye from"ora";import{spawn as be,execSync as we}from"child_process";import{fileURLToPath as C}from"url";import{createRequire as k}from"module";import{existsSync as L,readFileSync as D,writeFileSync as Z,mkdirSync as G}from"fs";import{join as W}from"path";import{homedir as F}from"os";var P=C(import.meta.url),Ae=A(P),Ce=k(import.meta.url);function u(o,e={},s={}){let i=["dolt","mem0"].includes(String(s.memoryBackend||"").toLowerCase())?String(s.memoryBackend).toLowerCase():"dolt",r={claude:`
2
+ claude: {
3
+ model: 'auto', // Options: 'auto', 'sonnet-4.6', 'opus-4.6', 'sonnet-4.5', 'opus-4.5'
4
+ maxTokens: 4096,
5
+ },`,cursor:`
6
+ cursor: {
7
+ model: 'auto', // Options: 'auto', 'opus-4.5', 'opus-4.5-thinking', 'sonnet-4.5', 'sonnet-4.5-thinking', 'composer-1', 'gpt-5.2-codex', 'gpt-5.2', 'gpt-5.3', 'gpt-5.4', 'gemini-3-pro', 'gemini-3-flash'
8
+ },`,codex:`
9
+ codex: {
10
+ model: 'gpt-5.2-codex', // Options: 'auto', 'o4-mini', 'o3', 'codex-mini', 'gpt-4o', 'gpt-5.2-codex', 'gpt-5.2', 'gpt-5.3', 'gpt-5.4'
11
+ },`,gemini:`
12
+ gemini: {
13
+ model: 'gemini-2.5-pro', // Options: 'auto', 'gemini-2.5-pro', 'gemini-2.5-flash'
14
+ },`},l=o.agent,p=Object.entries(r).filter(([c])=>c!==l).map(([,c])=>c.split(`
15
+ `).map(n=>n.trim()?` // ${n.trimStart()}`:n).join(`
16
+ `)).join(`
17
+ `);return`export default {
18
+ // AI agent settings
19
+ agent: {${r[l]}
20
+ ${p}
21
+ strictMode: false,
22
+ },
23
+
24
+ // Browser for Zibby MCP (execute_live). Wizard headed/headless is stored here for \`zibby run\` logs
25
+ // and workflow config. Runtime strategies attach MCP per run (no global Gemini settings mutation).
26
+ browser: {
27
+ mcp: 'playwright',
28
+ headless: ${o.browserMode==="headless"},
29
+ },
30
+
31
+ // Chat memory backend adapter (dolt | mem0)
32
+ memory: {
33
+ backend: '${i}',
34
+ },
35
+
36
+ // Advanced: Override models per node (optional)
37
+ // models: {
38
+ // default: 'auto', // Fallback for all nodes
39
+ // execute_live: 'claude-opus-4', // Override specific node
40
+ // },
41
+
42
+ // Folder paths
43
+ paths: {
44
+ specs: 'test-specs', // Where your .txt test specs are
45
+ generated: 'tests', // Where generated .spec.js files go
46
+ output: '.zibby/output', // Where workflow execution results are saved (default: .zibby/output)
47
+ workflows: '.zibby/workflows', // Where custom workflows are stored
48
+ // sessionPrefix: 'run', // Optional: prefix for session folders (e.g., run_1772788458045)
49
+ },
50
+
51
+ // Context discovery - auto-discovers CONTEXT.md & AGENTS.md files (cascades from root \u2192 spec directory)
52
+ // Override filenames to search for different files
53
+ context: {
54
+ filenames: ['CONTEXT.md', 'AGENTS.md'], // Auto-discover these files (walks up from spec directory)
55
+ discovery: {
56
+ env: \`env-\${process.env.ENV || 'local'}.js\`, // Additional explicit files
57
+ // fixtures: 'fixtures.js', // Add more as needed
58
+ }
59
+ },
60
+
61
+ // Video recording (affects playwright.config.js generation)
62
+ video: 'on', // Options: 'off', 'on', 'retain-on-failure', 'on-first-retry'
63
+
64
+ // Browser viewport size for test execution
65
+ // Default: 1280x720 (works well on most screens)
66
+ // For larger displays: { width: 1920, height: 1080 }
67
+ // For mobile testing: { width: 375, height: 667 } (iPhone SE)
68
+ viewport: { width: 1280, height: 720 },
69
+
70
+ // Playwright artifacts (screenshots, traces, videos)
71
+ // Traces contain EXACT selectors for 100% accurate script generation
72
+ // Default: true (stored in test-results/playwright, separate from workflow output)
73
+ playwrightArtifacts: true,
74
+
75
+ // Parallel runs: max concurrent \`zibby run\` processes from the chat agent (run_test) and
76
+ // the number of lanes on Studio Mission Control (when it can read this project\u2019s config).
77
+ parallel: {
78
+ maxConcurrentRuns: 8,
79
+ },
80
+
81
+ // Cloud sync - auto-upload test results & videos (requires ZIBBY_API_KEY in .env)
82
+ cloudSync: ${o.cloudSync||!1}
83
+ };
84
+ `}var _=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,h=["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"],b=["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 $(){let o=h[Math.floor(Math.random()*h.length)],e=b[Math.floor(Math.random()*b.length)];return`${o}-${e}`}function S(o){return`${o.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function z(o,e){return`/**
85
+ * ${o}
3
86
  *
4
87
  * buildGraph() \u2014 define nodes, edges, conditional routing
5
88
  * onComplete(result) \u2014 post-processing after the graph finishes
@@ -8,7 +91,7 @@ import{mkdir as d,writeFile as i}from"fs/promises";import{existsSync as b}from"f
8
91
  import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
9
92
  import { exampleNode } from './nodes/index.mjs';
10
93
 
11
- export class ${r} extends WorkflowAgent {
94
+ export class ${o} extends WorkflowAgent {
12
95
  buildGraph() {
13
96
  const graph = new WorkflowGraph();
14
97
 
@@ -24,8 +107,8 @@ export class ${r} extends WorkflowAgent {
24
107
  console.log(\`[${e}] workflow complete \u2014 success: \${result.success !== false}\`);
25
108
  }
26
109
  }
27
- `}function N(){return`export { exampleNode } from './example.mjs';
28
- `}function C(){return`import { z } from '@zibby/core';
110
+ `}function K(){return`export { exampleNode } from './example.mjs';
111
+ `}function M(){return`import { z } from '@zibby/core';
29
112
 
30
113
  const ExampleOutputSchema = z.object({
31
114
  summary: z.string().describe('A short summary of the result'),
@@ -44,16 +127,16 @@ Analyze the input and return a summary with a status.\`,
44
127
 
45
128
  outputSchema: ExampleOutputSchema,
46
129
  };
47
- `}function S(r,e){return`${JSON.stringify({name:r,description:`${e} workflow`,entryClass:e,triggers:{api:!0}},null,2)}
48
- `}function v(){return`${JSON.stringify({type:"module",dependencies:{"@zibby/core":"^0.1.33"}},null,2)}
49
- `}async function P(r){let e;r?e=r.toLowerCase():(e=$(),console.log(o.gray(`
50
- No name provided \u2014 generated: ${o.white(e)}`))),k.test(e)||(console.log(o.red(`
51
- 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
52
- `)),process.exit(1));let t=process.cwd(),a=".zibby/workflows";try{let s=await g(t);console.log(o.gray(` \u{1F4CB} Loaded config: workflows path = ${s?.paths?.workflows||"(not set)"}`)),a=s?.paths?.workflows||".zibby/workflows"}catch(s){console.log(o.yellow(` \u26A0\uFE0F Could not load .zibby.config.mjs: ${s.message}`)),console.log(o.gray(` Using default path: ${a}`))}let l=n(t,a,e),c=n(l,"nodes");b(l)&&(console.log(o.red(`
53
- Workflow already exists: ${a}/${e}/`)),console.log(o.gray(` Choose a different name or delete the existing folder.
54
- `)),process.exit(1));let m=j(e),p=x(` Scaffolding workflow "${e}"...`).start();try{await d(n(t,a),{recursive:!0}),await d(c,{recursive:!0}),await Promise.all([i(n(l,"graph.mjs"),z(m,e)),i(n(c,"index.mjs"),N()),i(n(c,"example.mjs"),C()),i(n(l,"workflow.json"),S(e,m)),i(n(l,"package.json"),v())]),p.succeed(` Scaffolded ${o.bold(e)}`),console.log(o.green(`
55
- Created:`)),console.log(o.white(` ${a}/${e}/`)),console.log(o.gray(` graph.mjs ${m} (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.gray(" package.json dependencies (@zibby/core)")),console.log(o.white(`
56
- Next steps:`)),console.log(o.cyan(` 1. Edit nodes in ${a}/${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}
57
- `))}catch(s){p.fail(" Scaffold failed"),console.log(o.red(`
58
- ${s.message}
59
- `)),process.exit(1)}}export{P as generateWorkflowCommand};
130
+ `}function j(o,e){return`${JSON.stringify({name:o,description:`${e} workflow`,entryClass:e,triggers:{api:!0}},null,2)}
131
+ `}function B(){return`${JSON.stringify({type:"module",dependencies:{"@zibby/core":"^0.1.33"}},null,2)}
132
+ `}async function Me(o){let e;o?e=o.toLowerCase():(e=$(),console.log(t.gray(`
133
+ No name provided \u2014 generated: ${t.white(e)}`))),_.test(e)||(console.log(t.red(`
134
+ Invalid workflow name: "${o}"`)),console.log(t.gray(" Must be lowercase, start with a letter, use only a-z, 0-9, hyphens")),console.log(t.gray(" Length: 2\u201364 characters")),console.log(t.gray(` Example: ticket-triage, pr-review, deploy-checker
135
+ `)),process.exit(1));let s=process.cwd(),i=".zibby/workflows";try{let n=await g(s);n?.paths?.workflows&&(i=n.paths.workflows)}catch(n){n?.message?.includes("not found")||(console.log(t.yellow(` \u26A0\uFE0F Could not load .zibby.config.mjs: ${n.message}`)),console.log(t.gray(` Using default path: ${i}`)))}let r=a(s,i,e),l=a(r,"nodes");y(r)&&(console.log(t.red(`
136
+ Workflow already exists: ${i}/${e}/`)),console.log(t.gray(` Choose a different name or delete the existing folder.
137
+ `)),process.exit(1));let p=S(e),c=E(` Scaffolding workflow "${e}"...`).start();try{await f(a(s,i),{recursive:!0}),await f(l,{recursive:!0}),await Promise.all([d(a(r,"graph.mjs"),z(p,e)),d(a(l,"index.mjs"),K()),d(a(l,"example.mjs"),M()),d(a(r,"workflow.json"),j(e,p)),d(a(r,"package.json"),B())]);let n=a(s,".zibby.config.mjs"),m=!1;if(!y(n)){let w=u({agent:"claude",browserMode:"headless"},{},{memoryBackend:"dolt"});await d(n,w),m=!0}c.succeed(` Scaffolded ${t.bold(e)}`),console.log(t.green(`
138
+ Created:`)),console.log(t.white(` ${i}/${e}/`)),console.log(t.gray(` graph.mjs ${p} (entry)`)),console.log(t.gray(" nodes/index.mjs barrel export")),console.log(t.gray(" nodes/example.mjs starter node (prompt + schema)")),console.log(t.gray(" workflow.json manifest")),console.log(t.gray(" package.json dependencies (@zibby/core)")),m&&console.log(t.white(" .zibby.config.mjs project config (agent: claude \u2014 edit to switch)")),console.log(t.white(`
139
+ Next steps:`)),console.log(t.cyan(` 1. Edit nodes in ${i}/${e}/nodes/`)),console.log(t.cyan(" 2. Wire them in graph.mjs")),console.log(t.cyan(" 3. Test locally:")),console.log(t.cyan(` zibby start ${e}`)),console.log(t.cyan(" 4. Deploy to cloud:")),console.log(t.cyan(` zibby deploy ${e}
140
+ `))}catch(n){c.fail(" Scaffold failed"),console.log(t.red(`
141
+ ${n.message}
142
+ `)),process.exit(1)}}export{Me as generateWorkflowCommand};
@@ -0,0 +1 @@
1
+ var t=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function e(r){return r?t.test(r)?{ok:!0}:{ok:!1,error:`'${r}' is not a UUID. Cloud workflows are identified by UUID only. Run \`zibby workflow list\` to find yours, or run \`zibby trigger\` with no argument for interactive selection.`}:{ok:!0}}export{t as TRIGGER_UUID_REGEX,e as validateTriggerUuid};
@@ -1,22 +1,22 @@
1
- import w from"ora";import{select as m}from"@inquirer/prompts";import{readFileSync as v,existsSync as B}from"fs";import{homedir as _}from"os";import{join as b}from"path";var $={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function y(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";$[e]?o=$[e].apiUrl:o=$.prod.apiUrl}try{let e=new URL(o);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),$.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),$.prod.apiUrl}}function U(){let o=b(_(),".zibby","config.json");if(B(o))try{let r=JSON.parse(v(o,"utf-8"));if(r.sessionToken)return r.sessionToken}catch{}let e=process.env.ZIBBY_API_KEY;if(e)return e;console.log(`
1
+ import y from"ora";import{select as I}from"@inquirer/prompts";import{readFileSync as $,existsSync as U}from"fs";import{homedir as k}from"os";import{join as j,resolve as _}from"path";var g={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function u(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";g[e]?o=g[e].apiUrl:o=g.prod.apiUrl}try{let e=new URL(o);return e.protocol!=="http:"&&e.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${e.protocol} (only http/https allowed)`),g.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),g.prod.apiUrl}}var b=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function m(o){return o?b.test(o)?{ok:!0}:{ok:!1,error:`'${o}' is not a UUID. Cloud workflows are identified by UUID only. Run \`zibby workflow list\` to find yours, or run \`zibby trigger\` with no argument for interactive selection.`}:{ok:!0}}function B(o){return o==="true"?!0:o==="false"?!1:o==="null"?null:o!==""&&!isNaN(Number(o))?Number(o):o}function E(o){let e={};for(let r of o||[]){let i=r.indexOf("=");if(i===-1){console.warn(` Warning: ignored param "${r}" \u2014 expected key=value format`);continue}let t=r.slice(0,i).trim(),n=B(r.slice(i+1)),c=t.split("."),l=e;for(let s=0;s<c.length-1;s++)(typeof l[c[s]]!="object"||l[c[s]]===null)&&(l[c[s]]={}),l=l[c[s]];l[c[c.length-1]]=n}return e}function N(o){let e=_(o);U(e)||(console.log(`
2
+ Error: --input-file not found: ${o}
3
+ `),process.exit(1));try{return JSON.parse($(e,"utf-8"))}catch(r){console.log(`
4
+ Error: --input-file is not valid JSON: ${r.message}
5
+ `),process.exit(1)}}function x(o){let e={};if(o.inputFile&&(e={...N(o.inputFile)}),o.input)try{e={...e,...JSON.parse(o.input)}}catch(r){console.log(`
6
+ Error: --input is not valid JSON`),console.log(` ${r.message}
7
+ `),process.exit(1)}return o.param?.length&&(e={...e,...E(o.param)}),e}function R(){let o=j(k(),".zibby","config.json");if(U(o))try{let r=JSON.parse($(o,"utf-8"));if(r.sessionToken)return r.sessionToken}catch{}let e=process.env.ZIBBY_API_KEY;if(e)return e;console.log(`
2
8
  Not authenticated`),console.log(" Run: zibby login"),console.log(` OR set ZIBBY_API_KEY env var (for CI/CD)
3
- `),process.exit(1)}async function E(o){let e=y(),r=w("Fetching projects...").start();try{let p=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});p.ok||(r.fail("Failed to fetch projects"),process.exit(1));let n=await p.json();Array.isArray(n)||(n.projects?n=n.projects:n.data&&(n=n.data)),(!n||n.length===0)&&(r.fail("No projects found"),process.exit(1)),r.succeed(`Found ${n.length} project${n.length===1?"":"s"}`),console.log("");let t=n.map(s=>({name:`${s.name||"Unnamed"} (${s.projectId||s.id})`,value:s.projectId||s.id}));return await m({message:"Select a project:",choices:t})}catch(p){r.fail(`Error: ${p.message}`),process.exit(1)}}async function T(o,e){let r=y(),p=w("Fetching deployed workflows...").start();try{let n=["analysis","implementation","run_test"],t=[];for(let i of n){let d=await fetch(`${r}/projects/${o}/workflows/${i}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(d.ok){let l=await d.json();l.graph&&t.push({name:i,version:l.version||0,isDefault:l.isDefault!==!1})}}t.length===0&&(p.fail("No deployed workflows found for this project"),process.exit(1)),p.succeed(`Found ${t.length} deployed workflow${t.length===1?"":"s"}`),console.log("");let s=t.map(i=>({name:`${i.name} (v${i.version})${i.isDefault?" [default]":""}`,value:i.name}));return await m({message:"Select a workflow to trigger:",choices:s})}catch(n){p.fail(`Error: ${n.message}`),process.exit(1)}}async function L(o,e={}){let r=U(),n=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(o),t=e.project||process.env.ZIBBY_PROJECT_ID,s=o;if(o&&n){let l=y();try{let a=await fetch(`${l}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(a.ok){let f=(await a.json()).projects||[];for(let c of f){let u=await fetch(`${l}/projects/${c.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(u.ok){let j=(await u.json()).find(I=>I.uuid===o);if(j){t=c.projectId,s=j.workflowType||j.name,console.log(`
4
- \u2713 Found workflow "${s}" (UUID: ${o})
5
- `);break}}}(!s||s===o)&&(console.log(`
9
+ `),process.exit(1)}async function T(o){let e=u(),r=y("Fetching projects...").start();try{let i=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});i.ok||(r.fail("Failed to fetch projects"),process.exit(1));let t=await i.json();Array.isArray(t)||(t.projects?t=t.projects:t.data&&(t=t.data)),(!t||t.length===0)&&(r.fail("No projects found"),process.exit(1)),r.succeed(`Found ${t.length} project${t.length===1?"":"s"}`),console.log("");let n=t.map(c=>({name:`${c.name||"Unnamed"} (${c.projectId||c.id})`,value:c.projectId||c.id}));return await I({message:"Select a project:",choices:n})}catch(i){r.fail(`Error: ${i.message}`),process.exit(1)}}async function A(o,e){let r=u(),i=y("Fetching deployed workflows...").start();try{let t=["analysis","implementation","run_test"],n=[];for(let l of t){let s=await fetch(`${r}/projects/${o}/workflows/${l}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(s.ok){let a=await s.json();a.graph&&n.push({name:l,version:a.version||0,isDefault:a.isDefault!==!1})}}n.length===0&&(i.fail("No deployed workflows found for this project"),process.exit(1)),i.succeed(`Found ${n.length} deployed workflow${n.length===1?"":"s"}`),console.log("");let c=n.map(l=>({name:`${l.name} (v${l.version})${l.isDefault?" [default]":""}`,value:l.name}));return await I({message:"Select a workflow to trigger:",choices:c})}catch(t){i.fail(`Error: ${t.message}`),process.exit(1)}}async function J(o,e={}){let r=m(o);r.ok||(console.log(`
10
+ Error: ${r.error}
11
+ `),process.exit(1));let i=R(),t=e.project||process.env.ZIBBY_PROJECT_ID,n;if(o){let s=u();try{let a=await fetch(`${s}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(a.ok){let d=(await a.json()).projects||[];for(let p of d){let w=await fetch(`${s}/projects/${p.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}});if(w.ok){let h=(await w.json()).find(v=>v.uuid===o);if(h){t=p.projectId,n=h.workflowType||h.name,console.log(`
12
+ \u2713 Found workflow "${n}" (UUID: ${o})
13
+ `);break}}}(!n||n===o)&&(console.log(`
6
14
  Error: Workflow with UUID "${o}" not found`),console.log(` Check: zibby workflow list
7
15
  `),process.exit(1))}}catch(a){console.log(`
8
16
  Error looking up workflow UUID: ${a.message}
9
- `),process.exit(1)}}else if(o&&!t){let l=y();try{let a=await fetch(`${l}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(a.ok){let f=(await a.json()).projects||[],c=[];for(let u of f){let h=await fetch(`${l}/projects/${u.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});h.ok&&(await h.json()).some(I=>I.workflowType===o)&&c.push(u)}if(c.length===1)t=c[0].projectId,console.log(`
10
- \u2713 Found workflow "${o}" in project: ${c[0].name||t}
11
- `);else if(c.length>1){console.log(`
12
- Workflow "${o}" is deployed to multiple projects:
13
- `);let u=c.map(h=>({name:`${h.name||"Unnamed"} (${h.projectId})`,value:h.projectId}));t=await m({message:"Select a project:",choices:u})}else console.log(`
14
- Error: Workflow "${o}" not found in any of your projects`),console.log(` Deploy it first with: zibby deploy ${o}
15
- `),process.exit(1)}}catch{}}t||(console.log(""),t=await E(r)),s||(console.log(""),s=await T(t,r));let i={};if(e.input)try{i=JSON.parse(e.input)}catch(l){console.log(`
16
- Error: Invalid JSON in --input`),console.log(` ${l.message}
17
- `),process.exit(1)}console.log(`
17
+ `),process.exit(1)}}t||(console.log(""),t=await T(i)),n||(console.log(""),n=await A(t,i));let c=x(e);if(console.log(`
18
18
  Triggering Workflow
19
- `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${s}`),console.log(` Project: ${t}`),Object.keys(i).length>0&&console.log(` Input: ${JSON.stringify(i).substring(0,50)}...`),e.idempotencyKey&&console.log(` Idempotency: ${e.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");let d=w("Triggering workflow execution...").start();try{let l=y(),a={input:i};e.idempotencyKey&&(a.idempotencyKey=e.idempotencyKey);let g=await fetch(`${l}/projects/${t}/workflows/${s}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`},body:JSON.stringify(a)});if(!g.ok){let c=await g.json().catch(()=>({}));g.status===429&&(d.fail("Quota exceeded"),console.log(`
20
- Your workflow execution quota has been exceeded`),c.quotaInfo&&(console.log(` Used: ${c.quotaInfo.used}/${c.quotaInfo.limit} executions`),console.log(` Plan: ${c.quotaInfo.planId}`),c.quotaInfo.periodEnd&&console.log(` Resets: ${new Date(c.quotaInfo.periodEnd).toLocaleDateString()}`)),console.log(""),process.exit(1)),d.fail("Trigger failed"),console.log(` Error: ${c.message||g.statusText}
21
- `),process.exit(1)}let f=await g.json();d.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${f.jobId}`),console.log(` Status: ${f.status}`),console.log(` Version: ${f.version}`),console.log(` Triggered: ${new Date(f.triggeredAt).toLocaleString()}`),console.log(""),console.log(" Monitor execution:"),o&&n?(console.log(` zibby logs ${o}`),console.log(` zibby logs ${o} -t`)):(console.log(` zibby logs --workflow ${s} --project ${t}`),console.log(` zibby logs --workflow ${s} --project ${t} -t`)),console.log("")}catch(l){d.fail("Trigger failed"),console.log(` Error: ${l.message}
22
- `),process.exit(1)}}export{L as triggerWorkflowCommand};
19
+ `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${n}`),console.log(` Project: ${t}`),Object.keys(c).length>0){let s=JSON.stringify(c);console.log(` Input: ${s.length>60?`${s.substring(0,57)}...`:s}`)}e.idempotencyKey&&console.log(` Idempotency: ${e.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");let l=y("Triggering workflow execution...").start();try{let s=u(),a={input:c};e.idempotencyKey&&(a.idempotencyKey=e.idempotencyKey);let f=await fetch(`${s}/projects/${t}/workflows/${n}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify(a)});if(!f.ok){let p=await f.json().catch(()=>({}));f.status===429&&(l.fail("Quota exceeded"),console.log(`
20
+ Your workflow execution quota has been exceeded`),p.quotaInfo&&(console.log(` Used: ${p.quotaInfo.used}/${p.quotaInfo.limit} executions`),console.log(` Plan: ${p.quotaInfo.planId}`),p.quotaInfo.periodEnd&&console.log(` Resets: ${new Date(p.quotaInfo.periodEnd).toLocaleDateString()}`)),console.log(""),process.exit(1)),l.fail("Trigger failed"),console.log(` Error: ${p.message||f.statusText}
21
+ `),process.exit(1)}let d=await f.json();l.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${d.jobId}`),console.log(` Status: ${d.status}`),console.log(` Version: ${d.version}`),console.log(` Triggered: ${new Date(d.triggeredAt).toLocaleString()}`),console.log(""),console.log(" Monitor execution:"),o?(console.log(` zibby logs ${o}`),console.log(` zibby logs ${o} -t`)):(console.log(` zibby logs --workflow ${n} --project ${t}`),console.log(` zibby logs --workflow ${n} --project ${t} -t`)),console.log("")}catch(s){l.fail("Trigger failed"),console.log(` Error: ${s.message}
22
+ `),process.exit(1)}}export{B as coerceValue,E as parseParams,x as resolveInput,J as triggerWorkflowCommand};
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "node ../scripts/build.mjs --extra-dirs bin",
11
- "test": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
11
+ "test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js",
12
12
  "test:unit": "vitest run src/",
13
13
  "test:auth": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
14
14
  "lint": "eslint .",
@@ -33,10 +33,10 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@aws-sdk/client-sqs": "^3.1038.0",
36
- "@zibby/workflow": "^0.1.0",
37
- "@zibby/core": "^0.1.30",
36
+ "@zibby/agent-workflow": "^0.1.2",
37
+ "@zibby/core": "^0.1.44",
38
38
  "@zibby/memory": "^0.1.5",
39
- "@zibby/skills": "^0.1.6",
39
+ "@zibby/skills": "^0.1.11",
40
40
  "adm-zip": "^0.5.17",
41
41
  "chalk": "^5.3.0",
42
42
  "cli-highlight": "^2.1.11",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "node ../scripts/build.mjs --extra-dirs bin",
11
- "test": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
11
+ "test": "vitest run test/auth*.test.js test/two-layer-auth.test.js test/trigger-params.test.js test/trigger-helpers.test.js test/deploy-helpers.test.js",
12
12
  "test:unit": "vitest run src/",
13
13
  "test:auth": "vitest run test/auth*.test.js test/two-layer-auth.test.js",
14
14
  "lint": "eslint .",
@@ -33,10 +33,10 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@aws-sdk/client-sqs": "^3.1038.0",
36
- "@zibby/workflow": "^0.1.0",
37
- "@zibby/core": "^0.1.30",
36
+ "@zibby/agent-workflow": "^0.1.2",
37
+ "@zibby/core": "^0.1.44",
38
38
  "@zibby/memory": "^0.1.5",
39
- "@zibby/skills": "^0.1.6",
39
+ "@zibby/skills": "^0.1.11",
40
40
  "adm-zip": "^0.5.17",
41
41
  "chalk": "^5.3.0",
42
42
  "cli-highlight": "^2.1.11",