@zibby/cli 0.1.77 → 0.1.79
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 +2 -2
- package/dist/commands/analyze-graph.js +5 -5
- package/dist/commands/workflow.js +5 -5
- package/dist/commands/workflows/dedicated-egress.js +44 -0
- package/dist/commands/workflows/deploy-helpers.js +1 -0
- package/dist/commands/workflows/deploy.js +15 -14
- package/dist/commands/workflows/logs.js +2 -2
- package/dist/commands/workflows/trigger-helpers.js +1 -0
- package/dist/commands/workflows/trigger.js +17 -17
- package/dist/package.json +5 -4
- package/package.json +5 -4
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
|
|
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,18 +1,18 @@
|
|
|
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}from"@zibby/
|
|
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}
|
|
6
6
|
`)}))},500);try{await r(e,"in_progress","",s);let n=await o(),h=((Date.now()-d)/1e3).toFixed(1);R=!0,clearInterval(T),await new Promise(g=>setImmediate(g)),console.log=f,process.stdout.write=m,S.trim()&&(l.push(S.trim()),S="");let w=l.join(`
|
|
7
7
|
`);if(i(`\u{1F4E1} [Middleware] Sending final update for ${e}: ${w.length} chars, ${l.length} total lines captured
|
|
8
|
-
`),n.success){await r(e,"success",w||`Completed in ${h}s`,s);let g=
|
|
8
|
+
`),n.success){await r(e,"success",w||`Completed in ${h}s`,s);let g=oe[e];if(g){let{key:$,value:y}=g(n);y&&await t(s,$,y)}}else await r(e,"failed",`${w}
|
|
9
9
|
|
|
10
10
|
Error: ${n.error}`,s);return n}catch(n){R=!0,clearInterval(T),await new Promise(w=>setImmediate(w)),console.log=f,process.stdout.write=m;let h=`${l.join(`
|
|
11
11
|
`)}
|
|
12
12
|
|
|
13
|
-
Error: ${n.message}`;throw await r(e,"failed",h,s),n}}}async function
|
|
14
|
-
\u{1F680} Zibby Analysis (Graph Mode)`),console.log(`@zibby/cli v${
|
|
13
|
+
Error: ${n.message}`;throw await r(e,"failed",h,s),n}}}async function re(r){let{EXECUTION_ID:t,TICKET_KEY:a,PROJECT_ID:e,REPOS:o,PROGRESS_QUEUE_URL:s,PROGRESS_API_URL:d,SQS_AUTH_TOKEN:l,PROJECT_API_TOKEN:u,GITHUB_TOKEN:f,MODEL:m}=process.env;(!t||!a||!e)&&(console.error("\u274C Missing required environment variables"),console.error(" Required: EXECUTION_ID, TICKET_KEY, PROJECT_ID"),process.exit(1));let i=await k(t,e),_=i.ticketContext,S=i.nodeConfigs||{},R=o?JSON.parse(o):i.repos,T=process.env.WORKSPACE||"/workspace",n=b(import.meta.resolve("@zibby/core/package.json")),h=L(G(n),"templates","code-analysis","prompts");console.log(`
|
|
14
|
+
\u{1F680} Zibby Analysis (Graph Mode)`),console.log(`@zibby/cli v${ee.version} | Node.js ${process.version}`),console.log("\u2500".repeat(60)),console.log(`Ticket: ${a}`),console.log(`Repositories: ${R.length}`),console.log(`Workspace: ${T}`),console.log(`AI Model: ${m||"auto"}`),console.log("\u2500".repeat(60));let w=te(A,N),g,$,y=null;if(r?.workflow){let c=J(process.cwd(),r.workflow);if(B(c)||(console.error(`\u274C Workflow file not found: ${c}`),process.exit(1)),c.endsWith(".js")||c.endsWith(".mjs"))try{let{pathToFileURL:p}=await import("url");y=await import(p(c).href),$=`local JS module (${c})`}catch(p){console.error(`\u274C Failed to load workflow JS module: ${p.message}`),process.exit(1)}else{try{let E=JSON.parse(j(c,"utf-8")),{_meta:C,...K}=E;g=K,$=`local file (${c})`}catch(E){console.error(`\u274C Failed to parse workflow file: ${E.message}`),process.exit(1)}let p=z(g);p.valid||(console.error("\u274C Invalid workflow file:"),p.errors.forEach(E=>console.error(` - ${E}`)),process.exit(1))}}else if(i.graphConfig)g=i.graphConfig,$="custom (from project workflow)";else{let c=new W;H(c),g=c.serialize(),$="default"}let O;if(y){let p={...y.nodeConfigs||{},...S};O=y.buildGraph({nodeMiddleware:w}),console.log(`\u{1F4D0} Graph source: ${$}`),console.log(` Nodes: ${O.nodes.size}`),S=p}else{if(S&&Object.keys(S).length>0){let c=g.nodeConfigs||{},p={...c};for(let[E,C]of Object.entries(S))p[E]={...c[E],...C};g.nodeConfigs=p}console.log(`\u{1F4D0} Graph source: ${$}`),console.log(` Nodes: ${g.nodes?.length||0}`),console.log(` Edges: ${g.edges?.length||0}`),O=Q(g,{nodeMiddleware:w,stateSchema:X,invokeAgent:q})}V(S);let x={EXECUTION_ID:t,PROGRESS_QUEUE_URL:s,PROGRESS_API_URL:d,SQS_AUTH_TOKEN:l,PROJECT_API_TOKEN:u,workspace:T,repos:R,ticketContext:_,promptsDir:h,githubToken:f,model:m,nodeConfigs:S};try{let p=(await O.run(null,x)).state,E=p.analyze_ticket_output?.validation||p.analyze_ticket_output?.analysis?.structured?.validation,C="completed";E&&!E.canProceed&&(C=E.status==="insufficient_context"?"insufficient_context":"blocked"),console.log(`
|
|
15
15
|
\u{1F4CB} Validation: canProceed=${E?.canProceed}, status=${E?.status}, finalStatus=${C}`),console.log(`
|
|
16
16
|
\u{1F4CA} Sending final status: ${C}`),await P(x,{status:C}),console.log(`
|
|
17
17
|
\u2705 Analysis completed successfully`),process.exit(0)}catch(c){if(console.error(`
|
|
18
|
-
\u274C Analysis failed:`,c.message),t)try{console.log("\u{1F4E1} Reporting failure..."),await P(x,{status:"failed",error:c.message})}catch{console.error("\u26A0\uFE0F Failed to report error")}process.exit(1)}}import.meta.url===`file://${process.argv[1]}`&&
|
|
18
|
+
\u274C Analysis failed:`,c.message),t)try{console.log("\u{1F4E1} Reporting failure..."),await P(x,{status:"failed",error:c.message})}catch{console.error("\u26A0\uFE0F Failed to report error")}process.exit(1)}}import.meta.url===`file://${process.argv[1]}`&&re();export{re as analyzeCommand};
|
|
@@ -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
|
|
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
|
|
@@ -8,7 +8,7 @@ import{readFileSync as N,writeFileSync as b,existsSync as B,mkdirSync as D}from"
|
|
|
8
8
|
--type is required`)),console.log(o.gray(` Built-in types: ${U.join(", ")}`)),console.log(o.gray(` Custom workflows: any lowercase slug (e.g., ticket-triage)
|
|
9
9
|
`)),process.exit(1)),!U.includes(e)&&!O.test(e)&&(console.log(o.red(`
|
|
10
10
|
Invalid workflow type: "${e}"`)),console.log(o.gray(` Built-in: ${U.join(", ")}`)),console.log(o.gray(` Custom: lowercase letters, digits, hyphens (2\u201364 chars)
|
|
11
|
-
`)),process.exit(1)),e}async function
|
|
11
|
+
`)),process.exit(1)),e}async function eo(t){let e=j(),{apiKey:l,projectId:c}=x(t),n=P(t);console.log(o.bold.cyan(`
|
|
12
12
|
Zibby Workflow Download
|
|
13
13
|
`)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(e.name)}`)),console.log(o.white(` Project: ${o.cyan(c)}`)),console.log(o.white(` Type: ${o.cyan(n)}`)),console.log(o.gray(" ".padEnd(52,"-")));let i=$(" Fetching workflow from cloud...").start();try{let g=_(),r=await fetch(`${g}/projects/${c}/workflows/${n}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`}});if(!r.ok){let a=await r.text();i.fail(` API error: ${r.status}`),console.log(o.red(` ${a}
|
|
14
14
|
`)),process.exit(1)}let s=await r.json();!s.graph&&s.isDefault?i.info(" No custom workflow saved -- downloading default graph"):i.succeed(` Fetched workflow (v${s.version||0})`);let d=s.graph||null;if(!d){console.log(o.yellow(`
|
|
@@ -21,7 +21,7 @@ import{readFileSync as N,writeFileSync as b,existsSync as B,mkdirSync as D}from"
|
|
|
21
21
|
Generated workflow files:`)),console.log(o.white(` ${o.bold(r)}`)),console.log(o.gray(" Executable graph with inline tool bindings")),console.log(o.white(` ${o.bold(v)}`)),console.log(o.gray(" Extra prompt instructions & runtime config")),console.log(o.white(` ${o.bold(p)}`)),console.log(o.gray(" Raw JSON config (for upload back to cloud)")),console.log(""),console.log(o.gray(` Version: ${e.version}`)),console.log(o.gray(` Nodes: ${e.graph.nodes?.length||0}`)),console.log(o.gray(` Edges: ${e.graph.edges?.length||0}
|
|
22
22
|
`)),console.log(o.white(" To run locally:")),console.log(o.cyan(` zibby analyze --workflow ${r}
|
|
23
23
|
`)),console.log(o.white(" To upload changes back:")),console.log(o.cyan(` zibby workflow upload --project ${e.projectId} --type ${t}
|
|
24
|
-
`))}async function
|
|
24
|
+
`))}async function no(t){let e=j(),{apiKey:l,projectId:c}=await Z(t),n=P(t);console.log(o.bold.cyan(`
|
|
25
25
|
Zibby Workflow Upload
|
|
26
26
|
`)),console.log(o.gray(" ".padEnd(52,"-"))),console.log(o.white(` Environment: ${o.cyan(e.name)}`)),console.log(o.white(` Project: ${o.cyan(c)}`)),console.log(o.white(` Type: ${o.cyan(n)}`)),console.log(o.gray(" ".padEnd(52,"-")));let i=process.cwd(),g=m(i,".zibby",`workflow-${n}.json`),r=m(i,".zibby",`workflow-${n}.js`),s=t.file||(B(r)?r:g);B(s)||(console.log(o.red(`
|
|
27
27
|
File not found: ${s}`)),console.log(o.gray(` Download a workflow first: zibby workflow download --project <id> --type <type>
|
|
@@ -39,9 +39,9 @@ import{readFileSync as N,writeFileSync as b,existsSync as B,mkdirSync as D}from"
|
|
|
39
39
|
Workflow "${n}" updated to version ${h.version}`)),console.log(o.gray(` Project: ${c}
|
|
40
40
|
`))}catch(p){I.fail(" Upload failed"),console.log(o.red(`
|
|
41
41
|
${p.message}
|
|
42
|
-
`)),process.exit(1)}}var J=["analysis","implementation","run_test"];async function
|
|
42
|
+
`)),process.exit(1)}}var J=["analysis","implementation","run_test"];async function to(t){let e=j(),{apiKey:l,projectId:c}=x(t);console.log(o.bold.cyan(`
|
|
43
43
|
Zibby Workflows
|
|
44
44
|
`));let n=$(" Fetching workflows...").start();try{let i=_(),g=[];for(let r of J){let s=await fetch(`${i}/projects/${c}/workflows/${r}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`}});if(s.ok){let d=await s.json();g.push({type:r,version:d.version||0,isDefault:d.isDefault!==!1&&!d.graph,nodes:d.graph?.nodes?.length||0,updatedAt:d.updatedAt||null})}}n.succeed(` Fetched workflows
|
|
45
45
|
`),console.log(o.gray(" ".padEnd(70,"-"))),console.log(o.white(" Type".padEnd(20))+o.white("Version".padEnd(10))+o.white("Nodes".padEnd(10))+o.white("Status".padEnd(15))+o.white("Updated")),console.log(o.gray(" ".padEnd(70,"-")));for(let r of g){let s=r.isDefault?o.gray("default"):o.green("custom"),d=r.updatedAt?new Date(r.updatedAt).toLocaleDateString():o.gray("-");console.log(` ${o.cyan(r.type.padEnd(18))}${String(r.version).padEnd(10)}${String(r.nodes).padEnd(10)}${s.padEnd(15)}${d}`)}console.log(o.gray(" ".padEnd(70,"-"))),console.log("")}catch(i){n.fail(" Failed to fetch workflows"),console.log(o.red(`
|
|
46
46
|
${i.message}
|
|
47
|
-
`)),process.exit(1)}}export{
|
|
47
|
+
`)),process.exit(1)}}export{eo as workflowDownloadCommand,to as workflowListCommand,no as workflowUploadCommand};
|
|
@@ -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
|
|
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
|
|
4
|
-
Error: No workflows found in ${
|
|
5
|
-
`),process.exit(1));let{readdir:
|
|
6
|
-
Error: No workflows found in ${
|
|
7
|
-
`),process.exit(1)),console.log(""),
|
|
8
|
-
Error: Workflow not found: ${
|
|
9
|
-
`),process.exit(1));let g=
|
|
10
|
-
Error: graph.mjs not found in ${
|
|
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: ${
|
|
13
|
-
`),process.exit(1)}let
|
|
14
|
-
`),process.exit(1)}r.text="Saving workflow definition...";let
|
|
15
|
-
`),process.exit(1)}let
|
|
16
|
-
`)
|
|
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};
|
|
@@ -18,9 +18,9 @@ import e from"chalk";import{readFileSync as R,existsSync as C}from"fs";import{ho
|
|
|
18
18
|
`));!a.value;){if(await new Promise(p=>setTimeout(p,5e3)),a.value)return;try{if(!(await T({token:s,executionId:n,sseEndpoint:f,stopped:a})).notFound)return}catch{}}else console.log(e.yellow(`
|
|
19
19
|
No executions found for this workflow. Trigger the workflow first.
|
|
20
20
|
`)),process.exit(1);if(r.failed){console.log(e.red(`
|
|
21
|
-
Execution failed.`)),t||process.exit(1);return}
|
|
21
|
+
Execution failed.`)),t||process.exit(1);return}if(r.completed&&process.exit(0),t&&!a.value)return console.log(e.gray(`
|
|
22
22
|
Connection ended, reconnecting...
|
|
23
|
-
`)),E({token:s,jobId:n,follow:t,projectId:null})
|
|
23
|
+
`)),E({token:s,jobId:n,follow:t,projectId:null})}catch(r){if(r.name==="AbortError"||a.value)return;if(console.error(e.red(` SSE Error: ${r.message}`)),t&&!a.value)return console.log(e.gray(`
|
|
24
24
|
Reconnecting...
|
|
25
25
|
`)),E({token:s,jobId:n,follow:t,projectId:null})}}async function v({token:s,projectId:n,jobId:t,follow:c,limit:f}){let a=n?`${I}/logs/${n}/${t}`:`${I}/job/${t}`,g=null,r=0,p=new Set,y=!1,w=0,$=5,h=()=>{y=!0,console.log(e.gray(`
|
|
26
26
|
Stopped tailing.
|
|
@@ -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
|
|
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
|
|
4
|
-
|
|
5
|
-
`);
|
|
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)}}
|
|
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: ${
|
|
20
|
-
Your workflow execution quota has been exceeded`),
|
|
21
|
-
`),process.exit(1)}let
|
|
22
|
-
`),process.exit(1)}}export{
|
|
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.
|
|
3
|
+
"version": "0.1.79",
|
|
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,9 +33,10 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
|
-
"@zibby/
|
|
36
|
+
"@zibby/agent-workflow": "^0.1.2",
|
|
37
|
+
"@zibby/core": "^0.1.44",
|
|
37
38
|
"@zibby/memory": "^0.1.5",
|
|
38
|
-
"@zibby/skills": "^0.1.
|
|
39
|
+
"@zibby/skills": "^0.1.11",
|
|
39
40
|
"adm-zip": "^0.5.17",
|
|
40
41
|
"chalk": "^5.3.0",
|
|
41
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.
|
|
3
|
+
"version": "0.1.79",
|
|
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,9 +33,10 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@aws-sdk/client-sqs": "^3.1038.0",
|
|
36
|
-
"@zibby/
|
|
36
|
+
"@zibby/agent-workflow": "^0.1.2",
|
|
37
|
+
"@zibby/core": "^0.1.44",
|
|
37
38
|
"@zibby/memory": "^0.1.5",
|
|
38
|
-
"@zibby/skills": "^0.1.
|
|
39
|
+
"@zibby/skills": "^0.1.11",
|
|
39
40
|
"adm-zip": "^0.5.17",
|
|
40
41
|
"chalk": "^5.3.0",
|
|
41
42
|
"cli-highlight": "^2.1.11",
|