@zibby/cli 0.1.61 → 0.1.62
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 +1 -1
- package/dist/commands/implement.js +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/workflows/delete.js +8 -0
- package/dist/commands/workflows/list.js +7 -7
- package/dist/commands/workflows/run.js +6 -6
- package/dist/commands/workflows/trigger.js +13 -7
- package/dist/package.json +5 -5
- package/dist/utils/progress-reporter.js +1 -1
- package/package.json +2 -2
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
|
|
3
|
-
`),C(process.cwd());const _=i[0]==="chat",x=["--verbose","--agent","--stream","-s"],A=i.length>0&&i.every(o=>x.includes(o)||i[i.indexOf(o)-1]==="--agent"),B=i.length===0||_||A;if(B&&!j){const o={},t=i.indexOf("--agent");t!==-1&&i[t+1]&&(o.agent=i[t+1]),i.includes("--verbose")&&(o.verbose=!0),(i.includes("--stream")||i.includes("-s"))&&(o.stream=!0);const{chatCommand:n}=await import("../commands/chat.js");await n(o),process.exit(0)}const e=new p;e.name("zibby").description("Zibby Test Automation - AI-powered test generation").version(r.version,"-V, --version"),e.command("init").description("Initialize a new Zibby test project (like rails new)").argument("[project-name]","Project name (optional, uses current directory if not provided)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini)").option("--memory-backend <backend>","Memory backend to configure (dolt, mem0)","dolt").option("--skip-install","Skip npm install").option("--skip-memory","Skip test memory setup during initialization").option("-f, --force","Force reinitialize (overwrite existing config)").option("--headed","Run MCP browser in headed mode (visible browser)").option("--headless","Run MCP browser in headless mode (hidden browser)").option("--api-key <key>","Zibby API key for cloud sync").option("--cloud-sync","Enable cloud sync and install Zibby MCP").action(d),e.command("test").description("Run a test specification").argument("[spec-path]","Path to test spec file or inline test description in quotes").option("--sources <ids>","Comma-separated test case IDs to fetch from cloud").option("--execution <id>","Execution ID containing the test cases (required with --sources)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini) - overrides config").option("--workflow <name>","Workflow to use (e.g., QuickSmokeWorkflow, quick-smoke)").option("--headless","Run browser in headless mode").option("--node <name>","Run only a specific node (e.g., execute_live, generate_script)").option("--session <id>",'Use existing session (e.g., 1768974629717 or "last") - requires --node').option("--session-path <dir>","Use this session folder (absolute or relative to cwd); Studio pins artifacts here").option("--project <id>","Project ID (optional, auto-detected from ZIBBY_API_KEY)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional, requires --collection)").option("--sync","Force upload to cloud (overrides cloudSync: false)").option("--no-sync","Skip upload to cloud (overrides cloudSync: true)").option("--config <path>","Path to config file",".zibby.config.mjs").option("--auto-approve","Auto-approve MCP tools (for CI/CD)").option("-o, --open","Open test results in browser after completion").option("--verbose","Show info level logs").option("--debug","Show debug level logs (most verbose)").option("-m, --mem","Enable test memory (Dolt-backed knowledge from previous runs)").action((o,t)=>(t.debug?process.env.ZIBBY_DEBUG="true":t.verbose&&(process.env.ZIBBY_VERBOSE="true"),l(o,t))),e.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...o)=>{const{implementCommand:t}=await import("../commands/implement.js");return t(...o)}),e.command("analyze").description("Analyze a Jira ticket against the codebase (runs in ECS container)").option("--workflow <path>","Path to a local workflow JSON file (e.g., .zibby/workflow-analysis.json)").action(async(...o)=>{const{analyzeCommand:t}=await import("../commands/analyze-graph.js");return t(...o)}),e.command("video").description("Organize test videos next to test files").action(m),e.command("upload <spec-path>").description("Upload existing test artifacts to Zibby Cloud").option("--project <id>","Project ID (REQUIRED - use flag or ZIBBY_PROJECT_ID env)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional)").option("--agent <type>","Agent used (for metadata)").action(u),e.command("login").description("Log in to Zibby (opens browser for authentication)").action(async()=>{const{loginCli:o}=await import("../auth/cli-login.js");await o(),process.exit(0)}),e.command("logout").description("Log out from Zibby (clears saved session)").action(async()=>{const{logoutCli:o}=await import("../auth/cli-login.js");o(),process.exit(0)}),e.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async o=>{const{showLoginStatus:t}=await import("../auth/cli-login.js");await t(o),process.exit(0)}),e.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:o}=await import("../commands/list-projects.js");await o()}),e.command("ci-setup").description("Setup Cursor Agent for CI/CD (patch and configure)").option("--get-keys","Get MCP approval keys").option("--save","Save approval keys to project").action(f),e.command("setup-playwright").description("Setup official Playwright MCP (from cursor-agent-package)").option("--headed","Configure MCP in headed mode (visible browser)").option("--viewport-width <width>","Viewport width (default: 1280)","1280").option("--viewport-height <height>","Viewport height (default: 720)","720").action(o=>{const t={width:parseInt(o.viewportWidth,10)||1280,height:parseInt(o.viewportHeight,10)||720};return w({...o,viewport:t})}),e.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(y),e.command("test-video").description("Run Playwright tests with video recording").argument("[test-file]","Test file to run (default: tests/)").option("--headed","Run in headed mode (visible browser)").action(g),e.command("generate").description("Generate test specs from a ticket + codebase (local analysis using real AI agent)").option("-t, --ticket <key>","Jira ticket key (fetches automatically)").option("-i, --input <file>","Input file with ticket description/requirements").option("-d, --description <text>","Inline ticket description").option("--repo <path>","Path to the codebase (default: current directory)").option("--agent <type>","Agent to use (codex, claude, cursor, gemini)").option("--model <model>","Model override").option("-o, --output <dir>","Output directory for spec files (default: test-specs)").action(async o=>{const{generateCommand:t}=await import("../commands/generate.js");return t(o)}),e.command("studio").description("Launch Zibby Studio desktop (installs from CDN if needed). Uses this folder as the Zibby project.").option("-p, --port <port>","Port for the Studio API bridge (default: 3847)").option("--no-open","Start the API only; do not launch desktop app").option("--update","Force re-download of the latest Studio binary").action(async o=>{const{studioCommand:t}=await import("../commands/studio.js");return t(o)});const E=e.command("g").description("Generate scaffolds");E.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").action(async o=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(o)}),e.command("start <workflow-name>").description("Start a local dev server for a custom workflow").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(o,t)=>{const{startWorkflowCommand:n}=await import("../commands/workflows/start.js");return n(o,t)}),e.command("deploy [workflow-name]").description("Deploy a custom workflow to Zibby Cloud (interactive selection if workflow-name not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(o,t)=>{const{deployWorkflowCommand:n}=await import("../commands/workflows/deploy.js");return n(o,t)}),e.command("trigger [workflow-name]").description("Trigger a deployed workflow to run in the cloud (interactive selection if not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--input <json>",`Input data as JSON string (e.g., '{"key":"value"}')`).option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").action(async(o,t)=>{const{triggerWorkflowCommand:n}=await import("../commands/workflows/trigger.js");return n(o,t)}),e.command("logs [jobId]").description("Tail logs from a workflow job or all executions of a workflow").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (tails the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --tail-latest","Auto-tail newest execution (scrollable history)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--no-follow","Fetch logs once and exit (default: tail)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(o,t)=>{const{logsCommand:n}=await import("../commands/workflows/logs.js");return n(o,t)}),e.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:o}=await import("../commands/workflows/run.js");return o()});const a=e.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");a.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:o}=await import("../commands/memory.js");return o()}),a.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:o}=await import("../commands/memory.js");return o()}),a.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async o=>{const{memoryCompactCommand:t}=await import("../commands/memory.js");return t(o)}),a.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async o=>{const{memoryResetCommand:t}=await import("../commands/memory.js");return t(o)});const c=e.command("workflow").description("Manage workflow graphs (download, upload, list)");c.command("download").description("Download a workflow graph from Zibby Cloud to .zibby/").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--type <type>","Workflow type: analysis, implementation, run_test").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--output <dir>","Output directory (default: .zibby/)").option("--include-default","Download the built-in default graph if no custom one exists").action(async o=>{const{workflowDownloadCommand:t}=await import("../commands/workflow.js");return t(o)}),c.command("list").description("List all workflows (local + remote if credentials available)").option("--local-only","Show only local workflows").option("--remote-only","Show only remote workflows (requires --project)").option("--project <id>","Project ID (optional, uses ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{if(o.remoteOnly){const{workflowListCommand:n}=await import("../commands/workflow.js");return n(o)}if(o.localOnly){const{listLocalWorkflowsCommand:n}=await import("../commands/workflows/list.js");return n(o)}const{listAllWorkflowsCommand:t}=await import("../commands/workflows/list.js");return t(o)});const D=e.command("project").description("Manage Zibby projects");D.command("list").description("List all projects").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async o=>{const{projectListCommand:t}=await import("../commands/project.js");return t(o)});const Z=e.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");Z.command("list").description("List CLI processes waiting for a run slot").option("--config <path>","Path to config file",".zibby.config.mjs").action(async o=>{const{runCapacityQueueListCommand:t}=await import("../commands/run-capacity-queue-cli.js");await t(o),process.exit(0)}),e.command("uninstall").description("Remove all Zibby data: global CLI, ~/.zibby, Cursor MCP config, Studio, and current project").option("--dry-run","Show what would be deleted without deleting").option("--deep","Also remove npx cache dirs containing zibby").action(async o=>{const{uninstallCommand:t}=await import("../commands/uninstall.js");await t(o),process.exit(0)}),e.parse();
|
|
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 h}from"../commands/setup-scripts.js";import{readFileSync as k}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),j=v(P),s=JSON.parse(k(C(j,"../package.json"),"utf-8")),c=`zibby v${s.version}`,i=process.argv.slice(2),S=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],x=i[1],A=["logs","uninstall"],D=d==="workflow"&&x==="list";!A.includes(d)&&!D&&console.log(`${c}
|
|
3
|
+
`),I(process.cwd());const B=i[0]==="chat",E=["--verbose","--agent","--stream","-s"],Z=i.length>0&&i.every(o=>E.includes(o)||i[i.indexOf(o)-1]==="--agent"),O=i.length===0||B||Z;if(O&&!S){const o={},t=i.indexOf("--agent");t!==-1&&i[t+1]&&(o.agent=i[t+1]),i.includes("--verbose")&&(o.verbose=!0),(i.includes("--stream")||i.includes("-s"))&&(o.stream=!0);const{chatCommand:n}=await import("../commands/chat.js");await n(o),process.exit(0)}const e=new 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(h),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("Tail logs from a workflow job or all executions of a workflow").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (tails the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --tail-latest","Auto-tail newest execution (scrollable history)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--no-follow","Fetch logs once and exit (default: tail)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(o,t)=>{const{logsCommand:n}=await import("../commands/workflows/logs.js");return n(o,t)}),e.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:o}=await import("../commands/workflows/run.js");return o()});const a=e.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");a.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:o}=await import("../commands/memory.js");return o()}),a.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:o}=await import("../commands/memory.js");return o()}),a.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async o=>{const{memoryCompactCommand:t}=await import("../commands/memory.js");return t(o)}),a.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async o=>{const{memoryResetCommand:t}=await import("../commands/memory.js");return t(o)});const 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();
|
|
@@ -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}from"@zibby/core/framework/graph-compiler.js";import{WorkflowGraph as W}from"@zibby/core/framework/graph.js";import{buildAnalysisGraph as q}from"@zibby/core/templates/code-analysis/graph.js";import{analysisStateSchema as H}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 N(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 A(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(
|
|
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/core/framework/graph-compiler.js";import{WorkflowGraph as W}from"@zibby/core/framework/graph.js";import{buildAnalysisGraph as q}from"@zibby/core/templates/code-analysis/graph.js";import{analysisStateSchema as H}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 N(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 A(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 X}from"@zibby/core/utils/mcp-config-writer.js";var V=b(import.meta.url),Y=G(V),Z=JSON.parse(j(L(Y,"../../package.json"),"utf-8")),ee={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 oe(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}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var A=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,n)=>(typeof require<"u"?require:r)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});import{existsSync as h,readFileSync as O,writeFileSync as J}from"fs";import{join as i,dirname as B}from"path";import{fileURLToPath as Q}from"url";import{invokeAgent as X}from"@zibby/core";async function b(t,r){let n=process.env.CONTEXT_PRESIGNED_URL;if(!n)throw new Error("CONTEXT_PRESIGNED_URL env var is required");console.log("\u{1F4E6} Fetching execution context via pre-signed URL");let o=await fetch(n);if(!o.ok)throw new Error(`Failed to fetch execution context: ${o.status}`);let e=await o.json();return console.log(` \u2705 Got ticketContext (${JSON.stringify(e.ticketContext||{}).length} chars)`),e.nodeConfigs&&Object.keys(e.nodeConfigs).length>0&&console.log(` \u2705 Got nodeConfigs (${Object.keys(e.nodeConfigs).length} nodes configured)`),{ticketContext:e.ticketContext||{},nodeConfigs:e.nodeConfigs||{},graphConfig:e.graphConfig||null,repos:e.repos||[]}}import{SQSClient as K,SendMessageCommand as F}from"@aws-sdk/client-sqs";var v=null;function G(){return v||(v=new K({region:process.env.AWS_REGION||"ap-southeast-2"})),v}async function k(t,r,n,o){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:s,PROGRESS_API_URL:c,PROGRESS_QUEUE_URL:f,PROJECT_API_TOKEN:a}=o;if(!e)return;let p={executionId:e,...s&&{sqsAuthToken:s},step:{name:t,status:r,logs:n,timestamp:new Date().toISOString(),...r==="success"&&{completedAt:new Date().toISOString()}},status:r==="failed"?"failed":"running"};try{c?await D(c,e,p,a):f&&await L(f,e,p)}catch(m){console.error(`\u26A0\uFE0F Failed to send progress: ${m.message}`)}}async function U(t,{status:r,error:n}){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:e,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:c,PROJECT_API_TOKEN:f}=t;if(!o)return;let a={executionId:o,...e&&{sqsAuthToken:e},status:r,...n&&{error:n},timestamp:new Date().toISOString()},p=s?"HTTP":c?"SQS":"NONE",m=JSON.stringify(a).length;console.log(
|
|
1
|
+
var A=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,n)=>(typeof require<"u"?require:r)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});import{existsSync as h,readFileSync as O,writeFileSync as J}from"fs";import{join as i,dirname as B}from"path";import{fileURLToPath as Q}from"url";import{invokeAgent as X}from"@zibby/core";async function b(t,r){let n=process.env.CONTEXT_PRESIGNED_URL;if(!n)throw new Error("CONTEXT_PRESIGNED_URL env var is required");console.log("\u{1F4E6} Fetching execution context via pre-signed URL");let o=await fetch(n);if(!o.ok)throw new Error(`Failed to fetch execution context: ${o.status}`);let e=await o.json();return console.log(` \u2705 Got ticketContext (${JSON.stringify(e.ticketContext||{}).length} chars)`),e.nodeConfigs&&Object.keys(e.nodeConfigs).length>0&&console.log(` \u2705 Got nodeConfigs (${Object.keys(e.nodeConfigs).length} nodes configured)`),{ticketContext:e.ticketContext||{},nodeConfigs:e.nodeConfigs||{},graphConfig:e.graphConfig||null,repos:e.repos||[]}}import{SQSClient as K,SendMessageCommand as F}from"@aws-sdk/client-sqs";var v=null;function G(){return v||(v=new K({region:process.env.AWS_REGION||"ap-southeast-2"})),v}async function k(t,r,n,o){let{EXECUTION_ID:e,SQS_AUTH_TOKEN:s,PROGRESS_API_URL:c,PROGRESS_QUEUE_URL:f,PROJECT_API_TOKEN:a}=o;if(!e)return;let p={executionId:e,...s&&{sqsAuthToken:s},step:{name:t,status:r,logs:n,timestamp:new Date().toISOString(),...r==="success"&&{completedAt:new Date().toISOString()}},status:r==="failed"?"failed":"running"};try{c?await D(c,e,p,a):f&&await L(f,e,p)}catch(m){console.error(`\u26A0\uFE0F Failed to send progress: ${m.message}`)}}async function U(t,{status:r,error:n}){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:e,PROGRESS_API_URL:s,PROGRESS_QUEUE_URL:c,PROJECT_API_TOKEN:f}=t;if(!o)return;let a={executionId:o,...e&&{sqsAuthToken:e},status:r,...n&&{error:n},timestamp:new Date().toISOString()},p=s?"HTTP":c?"SQS":"NONE",m=JSON.stringify(a).length;console.log(`Sending final status: ${r} via ${p} (${(m/1024).toFixed(1)}KB)`);try{if(s)await D(s,o,a,f);else if(c){let y=["completed","failed","insufficient_context","blocked"].includes(r)?"execution_completed":"progress_update";await L(c,o,a,y)}else{console.warn("No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`Final status ${r} sent via ${p}`)}catch(y){console.error(`Failed to send final status (${r}) via ${p}:`),console.error(` Payload: ${(m/1024).toFixed(1)}KB`),console.error(` Error: ${y.message}`),y.name&&console.error(` Error type: ${y.name}`),y.code&&console.error(` Error code: ${y.code}`)}}async function D(t,r,n,o){let e=`${t}/${r}/progress`,s={"Content-Type":"application/json"};o&&(s.Authorization=`Bearer ${o}`);let c=await fetch(e,{method:"POST",headers:s,body:JSON.stringify(n)});if(!c.ok){let f=await c.text();throw new Error(`HTTP ${c.status}: ${f}`)}}async function L(t,r,n,o="progress_update"){let e=JSON.stringify(n),s=(e.length/1024).toFixed(1);e.length>256*1024&&console.error(`\u274C SQS message too large: ${s}KB (limit 256KB) for ${r} [${o}]`),await G().send(new F({QueueUrl:t,MessageBody:e,MessageGroupId:r,MessageAttributes:{executionId:{DataType:"String",StringValue:r},messageType:{DataType:"String",StringValue:o}}}))}var H=Q(import.meta.url),M=B(H);async function ie(t){let{EXECUTION_ID:r,TICKET_KEY:n,PROJECT_ID:o,REPOS:e,_PRIMARY_REPO:s,_GITHUB_TOKEN:c,MODEL:f}=process.env;(!r||!n||!o)&&(console.error("\u274C Missing required environment variables:"),console.error(" EXECUTION_ID, TICKET_KEY, PROJECT_ID"),process.exit(1));let a=await b(r,o),p=a.ticketContext,m=e?JSON.parse(e):a.repos,y=m.find(w=>w.isPrimary)||m[0],_=process.cwd(),d={status:"running",steps:[]};try{await T("Start Environment",async()=>{}),await T("Clone Repositories",async()=>{let l=process.env.GITHUB_TOKEN,u=process.env.GITLAB_TOKEN||"",g=process.env.GITLAB_URL||"";for(let E of m){let R=i(_,E.name),S=E.url,I=E.provider==="gitlab"||g&&E.url.includes(new URL(g).host);if((E.provider==="github"||E.url.includes("github.com"))&&l)S=E.url.replace("https://github.com",`https://${l}@github.com`);else if(I&&u&&g)try{let P=new URL(g).host;S=E.url.replace(`https://${P}`,`https://oauth2:${u}@${P}`)}catch(P){console.warn(`\u26A0\uFE0F Failed to parse GITLAB_URL: ${P.message}`)}if(C(["git","clone",S,R],_),C(["git","checkout",E.branch],R),E.isPrimary){let P=`feature/${n.toLowerCase()}`;C(["git","checkout","-b",P],R)}}d.steps.push({name:"clone",status:"success",repoCount:m.length})});let w=await T("Load Ticket Context",async()=>(d.steps.push({name:"load_ticket",status:"success"}),p));await T("Install Dependencies",async()=>{for(let l of m){let u=i(_,l.name),g=j(u);try{C(g.installCommand,u)}catch{}}d.steps.push({name:"install_deps",status:"success"})});let $=await T("Detect Dev Command",async()=>{let l=i(_,y.name),u=["docker-compose.yml","docker-compose.yaml","compose.yml","compose.yaml"];for(let I of u)if(h(i(l,I)))return d.steps.push({name:"detect_dev",status:"success",command:"docker-compose up",type:"docker-compose"}),{command:"docker-compose up",type:"docker-compose",configFile:I};let g=i(l,"package.json");if(!h(g))return console.log(" \u26A0\uFE0F No package.json or docker-compose found"),d.steps.push({name:"detect_dev",status:"skipped"}),null;let R=JSON.parse(O(g,"utf-8")).scripts||{},S=null;return R.dev?S="npm run dev":R.start?S="npm start":R["dev:local"]&&(S="npm run dev:local"),S?(d.steps.push({name:"detect_dev",status:"success",command:S,type:"npm"}),{command:S,type:"npm"}):(d.steps.push({name:"detect_dev",status:"skipped"}),null)});await T("Start Dev Server",async()=>{let l=i(_,y.name),u="docker-compose.test.yml";return h(i(l,u))?(C(["docker","compose","-f",u,"up","-d"],l),await new Promise(g=>setTimeout(g,1e4)),d.steps.push({name:"start_server",status:"success"}),!0):(console.log(` \u26A0\uFE0F No ${u} found, skipping server startup`),d.steps.push({name:"start_server",status:"skipped"}),null)}),await T("Run AI Agent Implementation",async()=>{let l=m.map(E=>{let R=i(_,E.name);return{...E,...j(R)}}),u=q(w,l,$),g=i(_,".cursor-prompt.md");J(g,u),await X(u,{state:{model:f,workspace:_}},{print:!0}),d.steps.push({name:"ai_agent",status:"success"})});let Y=await T("Run E2E Tests",async()=>{let l=i(_,y.name);if(!h(i(l,"playwright.config.js"))&&!h(i(l,"playwright.config.ts")))return d.steps.push({name:"e2e_tests",status:"skipped"}),null;try{return C("npx playwright test --reporter=json",l),d.steps.push({name:"e2e_tests",status:"success"}),{passed:!0}}catch(u){throw C("docker compose -f docker-compose.test.yml down",l,{allowFailure:!0}),new Error(`E2E tests failed: ${u.message}`,{cause:u})}});try{C("docker compose -f docker-compose.test.yml down",i(_,y.name),{allowFailure:!0})}catch{}let x=await T("Create Pull Request",async()=>{let l=i(_,y.name),u=`feature/${n.toLowerCase()}`;return C(["git","add","."],l),C(["git","commit","-m",`feat(${n}): ${w.summary}`],l),C(["git","push","origin",u],l),console.log(" \u26A0\uFE0F PR creation via API removed (using SQS flow)"),d.steps.push({name:"create_pr",status:"skipped"}),null});await T("Report Results",async()=>{let l=i(_,y.name),u=i(l,"test-results"),g=[];h(u),d.status="completed",d.prUrl=x,d.videoUrls=g,await U(N(),{status:"completed",artifacts:{prUrl:x,videoUrls:g}})}),process.exit(0)}catch(w){console.error(""),console.error("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("\u2551 \u274C FAILED! \u2551"),console.error("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.error(""),console.error("Error:",w.message),console.error("Stack:",w.stack);try{await U(N(),{status:"failed",error:w.message})}catch($){console.error("Failed to report error:",$.message)}process.exit(1)}}function N(){return{EXECUTION_ID:process.env.EXECUTION_ID,PROGRESS_API_URL:process.env.PROGRESS_API_URL,PROGRESS_QUEUE_URL:process.env.PROGRESS_QUEUE_URL,SQS_AUTH_TOKEN:process.env.SQS_AUTH_TOKEN,PROJECT_API_TOKEN:process.env.PROJECT_API_TOKEN}}async function T(t,r){let n=Date.now(),o=[],e="",s=console.log;console.log=(...a)=>{let p=a.join(" ");o.push(p),s(...a)};let c=N(),f=setInterval(()=>{let a=o.join(`
|
|
2
2
|
`);a!==e&&a.length>0&&(e=a,k(t,"running",a,c).catch(()=>{}))},2e3);try{await k(t,"running","",c);let a=await r(),p=`${((Date.now()-n)/1e3).toFixed(1)}s`;clearInterval(f),console.log=s;let m=o.join(`
|
|
3
3
|
`);return await k(t,"success",m||`Completed in ${p}`,c),a}catch(a){clearInterval(f),console.log=s;let p=o.join(`
|
|
4
4
|
`);throw await k(t,"failed",`${p}
|
package/dist/commands/init.js
CHANGED
|
@@ -117,6 +117,7 @@ ${y}
|
|
|
117
117
|
specs: 'test-specs', // Where your .txt test specs are
|
|
118
118
|
generated: 'tests', // Where generated .spec.js files go
|
|
119
119
|
output: '.zibby/output', // Where workflow execution results are saved (default: .zibby/output)
|
|
120
|
+
workflows: '.zibby/workflows', // Where custom workflows are stored
|
|
120
121
|
// sessionPrefix: 'run', // Optional: prefix for session folders (e.g., run_1772788458045)
|
|
121
122
|
},
|
|
122
123
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import e from"chalk";import h from"ora";import{confirm as y,select as U}from"@inquirer/prompts";import{readFileSync as A,existsSync as $}from"fs";import{homedir as v}from"os";import{join as _}from"path";var d={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 r;if(process.env.ZIBBY_API_URL)r=process.env.ZIBBY_API_URL;else{let s=process.env.ZIBBY_ENV||"prod";d[s]?r=d[s].apiUrl:r=d.prod.apiUrl}try{let s=new URL(r);return s.protocol!=="http:"&&s.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${s.protocol} (only http/https allowed)`),d.prod.apiUrl):r}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${r}`),d.prod.apiUrl}}function B(){let r=_(v(),".zibby","config.json");$(r)||(console.log(e.red(`
|
|
2
|
+
Not authenticated`)),console.log(e.gray(` Run: zibby login
|
|
3
|
+
`)),process.exit(1));let s;try{s=JSON.parse(A(r,"utf-8"))}catch{console.log(e.red(`
|
|
4
|
+
Config file corrupt`)),console.log(e.gray(` Run: zibby login
|
|
5
|
+
`)),process.exit(1)}let t=s.sessionToken;return t||(console.log(e.red(`
|
|
6
|
+
Not authenticated`)),console.log(e.gray(` Run: zibby login
|
|
7
|
+
`)),process.exit(1)),t}async function j(r){let s=u(),t=h("Fetching projects...").start();try{let n=await fetch(`${s}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});n.ok||(t.fail("Failed to fetch projects"),process.exit(1));let o=await n.json();return Array.isArray(o)||(o.projects&&Array.isArray(o.projects)?o=o.projects:o.data&&Array.isArray(o.data)?o=o.data:(t.fail("Unexpected response format"),process.exit(1))),(!o||o.length===0)&&(t.fail("No projects found"),process.exit(1)),t.succeed(`Found ${o.length} project${o.length===1?"":"s"}`),console.log(""),await U({message:"Select a project:",choices:o.map(i=>({name:`${i.name||i.projectId} ${i.description?`(${i.description})`:""}`,value:i.projectId}))})}catch(n){t.fail(`Error: ${n.message}`),process.exit(1)}}async function N(r,s){let t=u();try{let n=await fetch(`${t}/projects/${s}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(!n.ok){let o=await n.json();throw new Error(o.error||"Failed to fetch workflows")}return await n.json()}catch(n){throw new Error(`Failed to fetch workflows: ${n.message}`,{cause:n})}}async function m(r,s){let t=u();try{let n=await fetch(`${t}/workflows/${s}`,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}});if(!n.ok){let o=await n.json();throw new Error(o.error||"Failed to delete workflow")}return await n.json()}catch(n){throw new Error(`Failed to delete workflow: ${n.message}`,{cause:n})}}async function z(r,s){try{let t=B();if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(r)){console.log(""),console.log(e.yellow("WARNING: This will permanently delete the workflow:")),console.log(e.white(` UUID: ${r}`)),console.log(""),await y({message:"Are you sure you want to delete this workflow?",default:!1})||(console.log(e.gray("Deletion cancelled")),process.exit(0));let c=h("Deleting workflow...").start();try{await m(t,r),c.succeed(e.green("Workflow deleted successfully"))}catch(I){c.fail(I.message),process.exit(1)}return}let o=r,w=s.project;w||(w=await j(t));let i=h("Fetching workflows...").start(),p;try{let l=await N(t,w);p=l.workflows||l,i.succeed(`Found ${p.length} workflow${p.length===1?"":"s"}`)}catch(l){i.fail(l.message),process.exit(1)}(!p||p.length===0)&&(console.log(e.yellow("No workflows found in this project")),process.exit(0));let k=["analysis","implementation","run_test"],f=p.filter(l=>!k.includes(l.workflowType));f.length===0&&(console.log(e.yellow("No custom workflows found in this project")),process.exit(0));let a;if(o)a=f.find(l=>l.workflowType===o),a||(console.error(e.red(`Workflow "${o}" not found`)),console.log(e.gray(`
|
|
8
|
+
Available workflows:`)),f.forEach(l=>{console.log(e.gray(` - ${l.workflowType}`))}),process.exit(1));else{console.log("");let l=await U({message:"Select workflow to delete:",choices:f.map(c=>({name:`${c.workflowType} ${c.version?`(v${c.version})`:""}`,value:c.workflowType}))});a=f.find(c=>c.workflowType===l)}console.log(""),console.log(e.yellow("WARNING: This will permanently delete the workflow:")),console.log(e.white(` Name: ${a.workflowType}`)),console.log(e.white(` UUID: ${a.uuid}`)),console.log(e.white(` Version: ${a.version||"N/A"}`)),console.log(""),await y({message:"Are you sure you want to delete this workflow?",default:!1})||(console.log(e.gray("Deletion cancelled")),process.exit(0));let g=h("Deleting workflow...").start();try{await m(t,a.uuid),g.succeed(e.green(`Workflow "${a.workflowType}" deleted successfully`))}catch(l){g.fail(l.message),process.exit(1)}}catch(t){console.error(e.red(`Error: ${t.message}`)),process.exit(1)}}export{z as deleteWorkflowCommand};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import{readdir as A,stat as
|
|
1
|
+
import{readdir as A,stat as z}from"fs/promises";import{existsSync as w}from"fs";import{join as g}from"path";import n from"chalk";import L from"dotenv";import{existsSync as j}from"fs";import{join as B}from"path";import{pathToFileURL as N}from"url";async function b(e){let r=B(e,".zibby.config.mjs");if(!j(r))throw new Error(".zibby.config.mjs not found");try{let t=await import(N(r).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}var u={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function I(){let e;if(process.env.ZIBBY_API_URL)e=process.env.ZIBBY_API_URL;else{let r=process.env.ZIBBY_ENV||"prod";u[r]?e=u[r].apiUrl:e=u.prod.apiUrl}try{let r=new URL(e);return r.protocol!=="http:"&&r.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${r.protocol} (only http/https allowed)`),u.prod.apiUrl):e}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${e}`),u.prod.apiUrl}}import{existsSync as x,mkdirSync as W,readFileSync as P,writeFileSync as M}from"fs";import{homedir as _}from"os";import{join as y}from"path";function $(){return process.env.ZIBBY_CONFIG_DIR||y(_(),".zibby")}function T(){return y($(),"config.json")}var C=y(_(),".zibby"),q=y(C,"config.json");function R(){try{let e=T();if(x(e)){let r=P(e,"utf-8");return JSON.parse(r)}}catch{}return{}}function k(){return R().sessionToken||null}L.config();async function D(e={}){let r=process.cwd(),t=".zibby/workflows";try{t=(await b(r))?.paths?.workflows||".zibby/workflows"}catch{}let d=g(r,t);if(!w(d))return e.quiet?[]:(console.log(n.yellow(`
|
|
2
2
|
No workflows found in ${t}/`)),console.log(n.gray(` Create one with: zibby g workflow <name>
|
|
3
|
-
`)),[]);try{let
|
|
3
|
+
`)),[]);try{let a=await A(d),l=[];for(let s of a){let i=g(d,s);if(!(await z(i)).isDirectory())continue;let c=w(g(i,"graph.mjs"))||w(g(i,"graph.js")),f=w(g(i,"workflow.json"));!c&&!f||l.push({name:s,hasGraph:c,hasManifest:f,path:`${t}/${s}`,source:"local"})}if(e.quiet)return l;if(l.length===0)return console.log(n.yellow(`
|
|
4
4
|
No workflows found in ${t}/`)),console.log(n.gray(` Create one with: zibby g workflow <name>
|
|
5
5
|
`)),[];console.log(n.bold.cyan(`
|
|
6
6
|
Local Workflows (${t})
|
|
7
7
|
`)),console.log(n.gray(" ".padEnd(60,"-"))),console.log(n.white(" Name".padEnd(35))+n.white("Files".padEnd(25))),console.log(n.gray(" ".padEnd(60,"-")));for(let s of l){let i=[];s.hasGraph&&i.push("graph"),s.hasManifest&&i.push("manifest"),console.log(` ${n.cyan(s.name.padEnd(33))}${n.gray(i.join(", "))}`)}return console.log(n.gray(" ".padEnd(60,"-"))),console.log(n.gray(`
|
|
8
8
|
Total: ${l.length} workflow${l.length===1?"":"s"}
|
|
9
|
-
`)),console.log(n.white(" Commands:")),console.log(n.cyan(" zibby start <name> ")+n.gray("Test locally")),console.log(n.cyan(" zibby deploy <name> ")+n.gray("Deploy to cloud")),console.log(n.cyan(" zibby trigger <name> ")+n.gray("Run workflow (returns job ID)")),console.log(n.cyan(" zibby logs <jobId> ")+n.gray("Tail execution logs")),console.log(""),l}catch(
|
|
10
|
-
Error reading workflows: ${
|
|
11
|
-
`)),process.exit(1)}}async function
|
|
9
|
+
`)),console.log(n.white(" Commands:")),console.log(n.cyan(" zibby start <name> ")+n.gray("Test locally")),console.log(n.cyan(" zibby deploy <name> ")+n.gray("Deploy to cloud")),console.log(n.cyan(" zibby trigger <name> ")+n.gray("Run workflow (returns job ID)")),console.log(n.cyan(" zibby logs <jobId> ")+n.gray("Tail execution logs")),console.log(""),l}catch(a){if(e.quiet)return[];console.log(n.red(`
|
|
10
|
+
Error reading workflows: ${a.message}
|
|
11
|
+
`)),process.exit(1)}}async function so(e={}){let r=await D({...e,quiet:!0}),t=[],d=k(),a=e.apiKey||process.env.ZIBBY_API_KEY,l=d||a;if(l)try{let o=I(),c=await fetch(`${o}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`}});if(c.ok){let h=(await c.json()).projects||[];for(let m of h){let U=await fetch(`${o}/projects/${m.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`}});if(U.ok){let v=await U.json(),E=["analysis","implementation","run_test"];for(let p of v)E.includes(p.workflowType)||t.push({uuid:p.uuid,name:p.workflowType,projectId:m.projectId,projectName:m.name||m.projectId,version:p.version||0,nodes:p.graphJson?JSON.parse(p.graphJson).nodes?.length:0,updatedAt:p.updatedAt||null,source:"remote"})}}}}catch{}let s=[],i=new Map(r.map(o=>[o.name,o]));for(let o of t){let c=i.has(o.name);s.push({uuid:o.uuid,name:o.name,project:o.projectName,source:c?"local+remote":"remote",nodes:o.nodes,version:o.version,hasLocal:c})}for(let[o,c]of i.entries())t.some(h=>h.name===o)||s.push({uuid:null,name:c.name,project:"-",source:"local",nodes:"-",version:"-",hasLocal:!0});if(s.length===0){console.log(`
|
|
12
12
|
No workflows found
|
|
13
13
|
`),console.log(` Create one with: zibby g workflow <name>
|
|
14
14
|
`);return}console.log(`
|
|
15
15
|
Workflows
|
|
16
|
-
`),console.log(" ".padEnd(
|
|
16
|
+
`),console.log(" ".padEnd(115,"-")),console.log(`${" UUID".padEnd(40)+"Name".padEnd(20)+"Project".padEnd(20)+"Source".padEnd(16)+"Nodes".padEnd(8)}Ver`),console.log(" ".padEnd(119,"-"));for(let o of s){let c=o.uuid?n.cyan(o.uuid):n.gray("-"),f=o.uuid?c+" ".repeat(4):c+" ".repeat(39);console.log(` ${f}${o.name.padEnd(20)}${o.project.padEnd(20)}${o.source.padEnd(16)}${String(o.nodes).padEnd(8)}${String(o.version)}`)}console.log(" ".padEnd(119,"-")),console.log(`
|
|
17
17
|
Total: ${s.length} workflow${s.length===1?"":"s"}
|
|
18
18
|
`),console.log(" Commands:"),console.log(" zibby start <name> Test locally"),console.log(" zibby deploy <name> Deploy to cloud (generates UUID)"),console.log(" zibby logs <uuid> View remote workflow logs"),l||console.log(`
|
|
19
|
-
Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{
|
|
19
|
+
Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{so as listAllWorkflowsCommand,D as listLocalWorkflowsCommand};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{mkdirSync as F,writeFileSync as L,existsSync as U}from"fs";import{join as E,dirname as W,resolve as y}from"path";import{pathToFileURL as D}from"url";import{SQSClient as k,SendMessageCommand as C}from"@aws-sdk/client-sqs";var S=null;function N(){return S||(S=new k({region:process.env.AWS_REGION||"ap-southeast-2"})),S}async function h(s,{status:e,error:o}){let{EXECUTION_ID:t,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:i,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:d}=s;if(!t)return;let l={executionId:t,...r&&{sqsAuthToken:r},status:e,...o&&{error:o},timestamp:new Date().toISOString()},p=i?"HTTP":n?"SQS":"NONE",f=JSON.stringify(l).length;console.log(
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import{mkdirSync as F,writeFileSync as L,existsSync as U}from"fs";import{join as E,dirname as W,resolve as y}from"path";import{pathToFileURL as D}from"url";import{SQSClient as k,SendMessageCommand as C}from"@aws-sdk/client-sqs";var S=null;function N(){return S||(S=new k({region:process.env.AWS_REGION||"ap-southeast-2"})),S}async function h(s,{status:e,error:o}){let{EXECUTION_ID:t,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:i,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:d}=s;if(!t)return;let l={executionId:t,...r&&{sqsAuthToken:r},status:e,...o&&{error:o},timestamp:new Date().toISOString()},p=i?"HTTP":n?"SQS":"NONE",f=JSON.stringify(l).length;console.log(`Sending final status: ${e} via ${p} (${(f/1024).toFixed(1)}KB)`);try{if(i)await v(i,t,l,d);else if(n){let c=["completed","failed","insufficient_context","blocked"].includes(e)?"execution_completed":"progress_update";await x(n,t,l,c)}else{console.warn("No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`Final status ${e} sent via ${p}`)}catch(c){console.error(`Failed to send final status (${e}) via ${p}:`),console.error(` Payload: ${(f/1024).toFixed(1)}KB`),console.error(` Error: ${c.message}`),c.name&&console.error(` Error type: ${c.name}`),c.code&&console.error(` Error code: ${c.code}`)}}async function v(s,e,o,t){let r=`${s}/${e}/progress`,i={"Content-Type":"application/json"};t&&(i.Authorization=`Bearer ${t}`);let n=await fetch(r,{method:"POST",headers:i,body:JSON.stringify(o)});if(!n.ok){let d=await n.text();throw new Error(`HTTP ${n.status}: ${d}`)}}async function x(s,e,o,t="progress_update"){let r=JSON.stringify(o),i=(r.length/1024).toFixed(1);r.length>256*1024&&console.error(`\u274C SQS message too large: ${i}KB (limit 256KB) for ${e} [${t}]`),await N().send(new C({QueueUrl:s,MessageBody:r,MessageGroupId:e,MessageAttributes:{executionId:{DataType:"String",StringValue:e},messageType:{DataType:"String",StringValue:t}}}))}var P=process.env.WORKSPACE||"/workspace";async function K(){let s=process.env.WORKFLOW_SOURCES_URL;if(!s)throw new Error("WORKFLOW_SOURCES_URL env var is required");console.log("Fetching workflow sources via pre-signed URL...");let e=await fetch(s);if(!e.ok)throw new Error(`Failed to fetch sources: ${e.status} ${e.statusText}`);let o=await e.json();if(!o.sources||typeof o.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return o}function b(s,e){let o=y(e),t=0;for(let[r,i]of Object.entries(s)){let n=y(e,r);if(!n.startsWith(`${o}/`)&&n!==o){console.error(` \u26D4 Skipping unsafe path: ${r}`);continue}F(W(n),{recursive:!0}),L(n,i,"utf-8"),t++}return t}async function G(s,e){let o=E(s,"graph.mjs");if(!U(o))throw new Error(`graph.mjs not found at ${o}`);let t=await import(D(o).href),r=e?.entryClass,i=r&&t[r]||t.default||Object.values(t).find(n=>typeof n=="function"&&n.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs");return i}async function z(){if(!process.env.NODE_PATH){process.env.NODE_PATH="/opt/zibby/packages";let a=await import("module");a.default._initPaths&&a.default._initPaths()}let{WORKFLOW_JOB_ID:s,WORKFLOW_TYPE:e,PROJECT_ID:o,AGENT_TYPE:t,MODEL:r}=process.env;e||(console.error("Missing WORKFLOW_TYPE env var"),process.exit(1)),console.log(`
|
|
3
|
+
Zibby Custom Workflow Runner`),console.log(` Job: ${s||"local"}`),console.log(` Workflow: ${e}`),console.log(` Project: ${o||"none"}`),console.log(` Agent: ${t||"default"}`),console.log(` Model: ${r||"auto"}`),console.log("\u2500".repeat(60));let i=await K(),{sources:n,input:d,workflowType:l,version:p}=i;console.log(` Workflow v${p||"?"} \u2014 ${Object.keys(n).length} source files`);let f=E(P,".zibby","workflows",l||e),c=b(n,f);console.log(` Wrote ${c} files to ${f}`),console.log(" Installing dependencies...");let{execSync:T}=await import("child_process");try{T("npm install --silent --no-audit --no-fund",{cwd:f,stdio:"inherit"}),console.log(" Dependencies installed")}catch(a){console.warn(` npm install failed: ${a.message}`)}let m={},O=E(f,"workflow.json");if(U(O)){let{readFileSync:a}=await import("fs");m=JSON.parse(a(O,"utf-8"))}let _=await G(f,m);console.log(` Loaded ${_.name}`);let I=Date.now(),u=new _({workflow:l||e}),R=u.buildGraph(),A={input:d||{},cwd:P,runId:s||`run-${Date.now()}`};console.log(`
|
|
4
|
+
Running graph (${R.nodes?.size||"?"} nodes)...
|
|
5
5
|
`);let g;try{g=await R.run(u,A)}catch(a){console.error(`
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Workflow execution failed: ${a.message}`),console.error(a.stack),await w("failed",a.message),process.exit(1)}let $=((Date.now()-I)/1e3).toFixed(1);g?.success!==!1?(console.log(`
|
|
7
|
+
Workflow "${l||e}" completed in ${$}s`),await w("completed")):(console.error(`
|
|
8
|
+
Workflow "${l||e}" failed after ${$}s`),await w("failed",g?.error||"Workflow execution failed"),process.exit(1)),u.onComplete&&await u.onComplete(g)}async function w(s,e=null){let o={EXECUTION_ID:process.env.WORKFLOW_JOB_ID,PROGRESS_API_URL:process.env.PROGRESS_API_URL,PROGRESS_QUEUE_URL:process.env.PROGRESS_QUEUE_URL};if(o.EXECUTION_ID)try{await h(o,{status:s,...e&&{error:e}})}catch(t){console.error(`\u26A0\uFE0F Failed to report status: ${t.message}`)}}export{z as runWorkflowCommand};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
`),process.exit(1));let n=e.
|
|
1
|
+
import h from"ora";import{select as y}from"@inquirer/prompts";import{readFileSync as $,existsSync as m}from"fs";import{homedir as j}from"os";import{join as U}from"path";var f={local:{name:"Local Development",apiUrl:"http://localhost:3001",accountApiUrl:"http://localhost:3001",frontendUrl:"http://localhost:3000",description:"Local backend running on port 3001"},prod:{name:"Production",apiUrl:process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app",accountApiUrl:process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app",frontendUrl:process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app",description:"Production environment"}};function g(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";f[e]?o=f[e].apiUrl:o=f.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)`),f.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),f.prod.apiUrl}}function v(){let o=U(j(),".zibby","config.json");if(m(o))try{let s=JSON.parse($(o,"utf-8"));if(s.sessionToken)return s.sessionToken}catch{}let e=process.env.ZIBBY_API_KEY;if(e)return e;console.log(`
|
|
2
|
+
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 w(o){let e=g(),s=h("Fetching projects...").start();try{let n=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}});n.ok||(s.fail("Failed to fetch projects"),process.exit(1));let t=await n.json();Array.isArray(t)||(t.projects?t=t.projects:t.data&&(t=t.data)),(!t||t.length===0)&&(s.fail("No projects found"),process.exit(1)),s.succeed(`Found ${t.length} project${t.length===1?"":"s"}`),console.log("");let l=t.map(r=>({name:`${r.name||"Unnamed"} (${r.projectId||r.id})`,value:r.projectId||r.id}));return await y({message:"Select a project:",choices:l})}catch(n){s.fail(`Error: ${n.message}`),process.exit(1)}}async function _(o,e){let s=g(),n=h("Fetching deployed workflows...").start();try{let t=["analysis","implementation","run_test"],l=[];for(let c of t){let p=await fetch(`${s}/projects/${o}/workflows/${c}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(p.ok){let a=await p.json();a.graph&&l.push({name:c,version:a.version||0,isDefault:a.isDefault!==!1})}}l.length===0&&(n.fail("No deployed workflows found for this project"),process.exit(1)),n.succeed(`Found ${l.length} deployed workflow${l.length===1?"":"s"}`),console.log("");let r=l.map(c=>({name:`${c.name} (v${c.version})${c.isDefault?" [default]":""}`,value:c.name}));return await y({message:"Select a workflow to trigger:",choices:r})}catch(t){n.fail(`Error: ${t.message}`),process.exit(1)}}async function x(o,e={}){let s=v(),n=e.project||process.env.ZIBBY_PROJECT_ID;if(o&&!n){let r=g();try{let c=await fetch(`${r}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`}});if(c.ok){let a=(await c.json()).projects||[],i=[];for(let u of a){let d=await fetch(`${r}/projects/${u.projectId}/workflows`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`}});d.ok&&(await d.json()).some(I=>I.workflowType===o)&&i.push(u)}if(i.length===1)n=i[0].projectId,console.log(`
|
|
4
|
+
\u2713 Found workflow "${o}" in project: ${i[0].name||n}
|
|
5
|
+
`);else if(i.length>1){console.log(`
|
|
6
|
+
Workflow "${o}" is deployed to multiple projects:
|
|
7
|
+
`);let u=i.map(d=>({name:`${d.name||"Unnamed"} (${d.projectId})`,value:d.projectId}));n=await y({message:"Select a project:",choices:u})}else console.log(`
|
|
8
|
+
Error: Workflow "${o}" not found in any of your projects`),console.log(` Deploy it first with: zibby deploy ${o}
|
|
9
|
+
`),process.exit(1)}}catch{}}n||(console.log(""),n=await w(s)),o||(console.log(""),o=await _(n,s));let t={};if(e.input)try{t=JSON.parse(e.input)}catch(r){console.log(`
|
|
4
10
|
Error: Invalid JSON in --input`),console.log(` ${r.message}
|
|
5
11
|
`),process.exit(1)}console.log(`
|
|
6
12
|
Triggering Workflow
|
|
7
|
-
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${
|
|
8
|
-
Your workflow execution quota has been exceeded`),
|
|
9
|
-
`),process.exit(1)}let
|
|
10
|
-
`),process.exit(1)}}export{
|
|
13
|
+
`),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${o}`),console.log(` Project: ${n}`),Object.keys(t).length>0&&console.log(` Input: ${JSON.stringify(t).substring(0,50)}...`),e.idempotencyKey&&console.log(` Idempotency: ${e.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");let l=h("Triggering workflow execution...").start();try{let r=g(),c={input:t};e.idempotencyKey&&(c.idempotencyKey=e.idempotencyKey);let p=await fetch(`${r}/projects/${n}/workflows/${o}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(c)});if(!p.ok){let i=await p.json().catch(()=>({}));p.status===429&&(l.fail("Quota exceeded"),console.log(`
|
|
14
|
+
Your workflow execution quota has been exceeded`),i.quotaInfo&&(console.log(` Used: ${i.quotaInfo.used}/${i.quotaInfo.limit} executions`),console.log(` Plan: ${i.quotaInfo.planId}`),i.quotaInfo.periodEnd&&console.log(` Resets: ${new Date(i.quotaInfo.periodEnd).toLocaleDateString()}`)),console.log(""),process.exit(1)),l.fail("Trigger failed"),console.log(` Error: ${i.message||p.statusText}
|
|
15
|
+
`),process.exit(1)}let a=await p.json();l.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${a.jobId}`),console.log(` Status: ${a.status}`),console.log(` Version: ${a.version}`),console.log(` Triggered: ${new Date(a.triggeredAt).toLocaleString()}`),console.log(""),console.log(" Monitor execution:"),console.log(` zibby logs ${a.jobId}`),console.log(` zibby logs --workflow ${o}`),console.log("")}catch(r){l.fail("Trigger failed"),console.log(` Error: ${r.message}
|
|
16
|
+
`),process.exit(1)}}export{x as triggerWorkflowCommand};
|
package/dist/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"zibby": "./
|
|
7
|
+
"zibby": "./bin/zibby.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "node ../scripts/build.mjs --extra-dirs bin",
|
|
@@ -45,15 +45,15 @@
|
|
|
45
45
|
"glob": "^13.0.0",
|
|
46
46
|
"handlebars": "^4.7.9",
|
|
47
47
|
"inquirer": "^13.4.1",
|
|
48
|
-
"mem0ai": "npm:@zibby/mem0ai@^
|
|
48
|
+
"mem0ai": "npm:@zibby/mem0ai@^3.0.2",
|
|
49
49
|
"open": "^10.2.0",
|
|
50
50
|
"ora": "^8.0.1",
|
|
51
51
|
"tar": "^7.5.2",
|
|
52
52
|
"ws": "^8.20.0"
|
|
53
53
|
},
|
|
54
54
|
"files": [
|
|
55
|
-
"
|
|
56
|
-
"
|
|
55
|
+
"bin/",
|
|
56
|
+
"src/",
|
|
57
57
|
"README.md",
|
|
58
58
|
"LICENSE"
|
|
59
59
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SQSClient as _,SendMessageCommand as u}from"@aws-sdk/client-sqs";var E=null;function O(){return E||(E=new _({region:process.env.AWS_REGION||"ap-southeast-2"})),E}async function $(c,e,s,o){let{EXECUTION_ID:t,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:n,PROGRESS_QUEUE_URL:S,PROJECT_API_TOKEN:l}=o;if(!t)return;let a={executionId:t,...r&&{sqsAuthToken:r},step:{name:c,status:e,logs:s,timestamp:new Date().toISOString(),...e==="success"&&{completedAt:new Date().toISOString()}},status:e==="failed"?"failed":"running"};try{n?await f(n,t,a,l):S&&await p(S,t,a)}catch(d){console.error(`\u26A0\uFE0F Failed to send progress: ${d.message}`)}}async function m(c,e,s){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:t,PROGRESS_API_URL:r,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:S}=c;if(!o||!s)return;let l=JSON.stringify(s).length;console.log(
|
|
1
|
+
import{SQSClient as _,SendMessageCommand as u}from"@aws-sdk/client-sqs";var E=null;function O(){return E||(E=new _({region:process.env.AWS_REGION||"ap-southeast-2"})),E}async function $(c,e,s,o){let{EXECUTION_ID:t,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:n,PROGRESS_QUEUE_URL:S,PROJECT_API_TOKEN:l}=o;if(!t)return;let a={executionId:t,...r&&{sqsAuthToken:r},step:{name:c,status:e,logs:s,timestamp:new Date().toISOString(),...e==="success"&&{completedAt:new Date().toISOString()}},status:e==="failed"?"failed":"running"};try{n?await f(n,t,a,l):S&&await p(S,t,a)}catch(d){console.error(`\u26A0\uFE0F Failed to send progress: ${d.message}`)}}async function m(c,e,s){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:t,PROGRESS_API_URL:r,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:S}=c;if(!o||!s)return;let l=JSON.stringify(s).length;console.log(`Sending artifact: ${e} (${(l/1024).toFixed(1)}KB)`);let a={executionId:o,...t&&{sqsAuthToken:t},artifacts:{[e]:s},timestamp:new Date().toISOString()},d=r?"HTTP":n?"SQS":"NONE",i=JSON.stringify(a).length;try{if(r)await f(r,o,a,S);else if(n)await p(n,o,a);else{console.warn(`\u26A0\uFE0F No transport configured for artifact ${e} \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set`);return}console.log(`Artifact ${e} sent via ${d} (payload=${(i/1024).toFixed(1)}KB, value=${(l/1024).toFixed(1)}KB)`)}catch(g){console.error(`Failed to send artifact ${e} via ${d}:`),console.error(` Payload size: ${(i/1024).toFixed(1)}KB, Value size: ${(l/1024).toFixed(1)}KB`),console.error(` Error: ${g.message}`),g.name&&console.error(` Error type: ${g.name}`),g.code&&console.error(` Error code: ${g.code}`),i>256*1024&&console.error(" \u26A0\uFE0F Message exceeds SQS 256KB limit! Consider splitting or compressing.")}}async function P(c,{status:e,error:s}){let{EXECUTION_ID:o,SQS_AUTH_TOKEN:t,PROGRESS_API_URL:r,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:S}=c;if(!o)return;let l={executionId:o,...t&&{sqsAuthToken:t},status:e,...s&&{error:s},timestamp:new Date().toISOString()},a=r?"HTTP":n?"SQS":"NONE",d=JSON.stringify(l).length;console.log(`Sending final status: ${e} via ${a} (${(d/1024).toFixed(1)}KB)`);try{if(r)await f(r,o,l,S);else if(n){let i=["completed","failed","insufficient_context","blocked"].includes(e)?"execution_completed":"progress_update";await p(n,o,l,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 ${e} sent via ${a}`)}catch(i){console.error(`Failed to send final status (${e}) via ${a}:`),console.error(` Payload: ${(d/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 f(c,e,s,o){let t=`${c}/${e}/progress`,r={"Content-Type":"application/json"};o&&(r.Authorization=`Bearer ${o}`);let n=await fetch(t,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok){let S=await n.text();throw new Error(`HTTP ${n.status}: ${S}`)}}async function p(c,e,s,o="progress_update"){let t=JSON.stringify(s),r=(t.length/1024).toFixed(1);t.length>256*1024&&console.error(`\u274C SQS message too large: ${r}KB (limit 256KB) for ${e} [${o}]`),await O().send(new u({QueueUrl:c,MessageBody:t,MessageGroupId:e,MessageAttributes:{executionId:{DataType:"String",StringValue:e},messageType:{DataType:"String",StringValue:o}}}))}export{m as reportArtifact,P as reportFinalStatus,$ as reportProgress};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"glob": "^13.0.0",
|
|
46
46
|
"handlebars": "^4.7.9",
|
|
47
47
|
"inquirer": "^13.4.1",
|
|
48
|
-
"mem0ai": "npm:@zibby/mem0ai@^
|
|
48
|
+
"mem0ai": "npm:@zibby/mem0ai@^3.0.2",
|
|
49
49
|
"open": "^10.2.0",
|
|
50
50
|
"ora": "^8.0.1",
|
|
51
51
|
"tar": "^7.5.2",
|