@zibby/cli 0.1.59 → 0.1.61

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.
Files changed (40) hide show
  1. package/dist/auth/cli-login.js +12 -12
  2. package/dist/bin/zibby.js +2 -2
  3. package/dist/commands/agent-reliability.js +4 -4
  4. package/dist/commands/analyze-graph.js +14 -14
  5. package/dist/commands/chat-session-store.js +1 -1
  6. package/dist/commands/chat.js +71 -62
  7. package/dist/commands/ci-setup.js +3 -3
  8. package/dist/commands/generate.js +60 -21
  9. package/dist/commands/implement.js +15 -15
  10. package/dist/commands/init.js +87 -67
  11. package/dist/commands/list-projects.js +9 -9
  12. package/dist/commands/memory.js +13 -13
  13. package/dist/commands/project.js +15 -0
  14. package/dist/commands/run-capacity-queue-cli.js +2 -2
  15. package/dist/commands/run.js +52 -50
  16. package/dist/commands/setup-scripts.js +6 -6
  17. package/dist/commands/studio.js +21 -15
  18. package/dist/commands/uninstall.js +10 -10
  19. package/dist/commands/upload.js +15 -15
  20. package/dist/commands/video.js +1 -1
  21. package/dist/commands/workflow.js +36 -34
  22. package/dist/commands/workflows/deploy.js +14 -24
  23. package/dist/commands/workflows/generate.js +15 -14
  24. package/dist/commands/workflows/list.js +19 -0
  25. package/dist/commands/workflows/logs.js +28 -19
  26. package/dist/commands/workflows/run.js +7 -7
  27. package/dist/commands/workflows/start.js +6 -6
  28. package/dist/commands/workflows/trigger.js +10 -0
  29. package/dist/config/config-loader.js +1 -0
  30. package/dist/config/config.js +1 -1
  31. package/dist/config/environments.js +1 -1
  32. package/dist/package.json +4 -4
  33. package/dist/utils/agent-credentials.js +3 -3
  34. package/dist/utils/chat-run-lifecycle.js +3 -3
  35. package/dist/utils/execution-context.js +1 -1
  36. package/dist/utils/progress-reporter.js +1 -1
  37. package/dist/utils/studio-cli-log-mirror.js +1 -1
  38. package/dist/utils/studio-installer.js +5 -5
  39. package/dist/utils/studio-launcher.js +1 -1
  40. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{mkdir as d,writeFile as a}from"fs/promises";import{existsSync as u}from"fs";import{join as t}from"path";import o from"chalk";import f from"ora";const h=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,c=["stellar","quantum","cosmic","nova","nebula","solar","lunar","atomic","plasma","fusion","pulse","flux","spark","blaze","ember","radiant","luminous","electric","magnetic","kinetic","neon","cyber","pixel","matrix","vector","synth","neural","prism","zenith","phoenix","catalyst","nexus","echo","wave","crystal","jade","ruby","emerald","onyx","amber","silver","turbo","lightning","thunder","storm","arcane","mystic","ethereal","celestial","swift","crimson","iron","cobalt"],m=["flow","runner","pipeline","stream","circuit","engine","beacon","forge","relay","shuttle","conduit","gateway","sentinel","scout","pilot","voyager","ranger","dispatch","signal","pulse","agent","daemon","spark","orbit","vector","nexus","matrix","grid","mesh","bridge","link","node","craft","bolt","ray","arc","wave","hook","probe","shard"];function y(){const r=c[Math.floor(Math.random()*c.length)],e=m[Math.floor(Math.random()*m.length)];return`${r}-${e}`}function w(r){return`${r.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function x(r,e){return`/**
1
+ import{mkdir as d,writeFile as i}from"fs/promises";import{existsSync as b}from"fs";import{join as n}from"path";import o from"chalk";import x from"ora";import{existsSync as h}from"fs";import{join as y}from"path";import{pathToFileURL as w}from"url";async function g(r){let e=y(r,".zibby.config.mjs");if(!h(e))throw new Error(".zibby.config.mjs not found");try{let t=await import(w(e).href);return t.default||t}catch(t){throw new Error(`Failed to load .zibby.config.mjs: ${t.message}`,{cause:t})}}var k=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/,f=["stellar","quantum","cosmic","nova","nebula","solar","lunar","atomic","plasma","fusion","pulse","flux","spark","blaze","ember","radiant","luminous","electric","magnetic","kinetic","neon","cyber","pixel","matrix","vector","synth","neural","prism","zenith","phoenix","catalyst","nexus","echo","wave","crystal","jade","ruby","emerald","onyx","amber","silver","turbo","lightning","thunder","storm","arcane","mystic","ethereal","celestial","swift","crimson","iron","cobalt"],u=["flow","runner","pipeline","stream","circuit","engine","beacon","forge","relay","shuttle","conduit","gateway","sentinel","scout","pilot","voyager","ranger","dispatch","signal","pulse","agent","daemon","spark","orbit","vector","nexus","matrix","grid","mesh","bridge","link","node","craft","bolt","ray","arc","wave","hook","probe","shard"];function $(){let r=f[Math.floor(Math.random()*f.length)],e=u[Math.floor(Math.random()*u.length)];return`${r}-${e}`}function j(r){return`${r.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function z(r,e){return`/**
2
2
  * ${r}
3
3
  *
4
4
  * buildGraph() \u2014 define nodes, edges, conditional routing
@@ -24,8 +24,8 @@ export class ${r} extends WorkflowAgent {
24
24
  console.log(\`[${e}] workflow complete \u2014 success: \${result.success !== false}\`);
25
25
  }
26
26
  }
27
- `}function b(){return`export { exampleNode } from './example.mjs';
28
- `}function k(){return`import { z } from '@zibby/core';
27
+ `}function N(){return`export { exampleNode } from './example.mjs';
28
+ `}function C(){return`import { z } from '@zibby/core';
29
29
 
30
30
  const ExampleOutputSchema = z.object({
31
31
  summary: z.string().describe('A short summary of the result'),
@@ -44,15 +44,16 @@ Analyze the input and return a summary with a status.\`,
44
44
 
45
45
  outputSchema: ExampleOutputSchema,
46
46
  };
47
- `}function $(r,e){return`${JSON.stringify({name:r,description:`${e} workflow`,entryClass:e,triggers:{api:!0}},null,2)}
48
- `}async function W(r){let e;r?e=r.toLowerCase():(e=y(),console.log(o.gray(`
49
- No name provided \u2014 generated: ${o.white(e)}`))),h.test(e)||(console.log(o.red(`
47
+ `}function S(r,e){return`${JSON.stringify({name:r,description:`${e} workflow`,entryClass:e,triggers:{api:!0}},null,2)}
48
+ `}function v(){return`${JSON.stringify({type:"module",dependencies:{"@zibby/core":"^0.1.33"}},null,2)}
49
+ `}async function P(r){let e;r?e=r.toLowerCase():(e=$(),console.log(o.gray(`
50
+ No name provided \u2014 generated: ${o.white(e)}`))),k.test(e)||(console.log(o.red(`
50
51
  Invalid workflow name: "${r}"`)),console.log(o.gray(" Must be lowercase, start with a letter, use only a-z, 0-9, hyphens")),console.log(o.gray(" Length: 2\u201364 characters")),console.log(o.gray(` Example: ticket-triage, pr-review, deploy-checker
51
- `)),process.exit(1));const p=process.cwd(),n=t(p,".zibby","workflows",e),s=t(n,"nodes");u(n)&&(console.log(o.red(`
52
- Workflow already exists: .zibby/workflows/${e}/`)),console.log(o.gray(` Choose a different name or delete the existing folder.
53
- `)),process.exit(1));const l=w(e),i=f(` Scaffolding workflow "${e}"...`).start();try{await d(s,{recursive:!0}),await Promise.all([a(t(n,"graph.mjs"),x(l,e)),a(t(s,"index.mjs"),b()),a(t(s,"example.mjs"),k()),a(t(n,"workflow.json"),$(e,l))]),i.succeed(` Scaffolded ${o.bold(e)}`),console.log(o.green(`
54
- Created:`)),console.log(o.white(` .zibby/workflows/${e}/`)),console.log(o.gray(` graph.mjs ${l} (entry)`)),console.log(o.gray(" nodes/index.mjs barrel export")),console.log(o.gray(" nodes/example.mjs starter node (prompt + schema)")),console.log(o.gray(" workflow.json manifest")),console.log(o.white(`
55
- Next steps:`)),console.log(o.cyan(` 1. Edit nodes in .zibby/workflows/${e}/nodes/`)),console.log(o.cyan(" 2. Wire them in graph.mjs")),console.log(o.cyan(" 3. Test locally:")),console.log(o.cyan(` zibby start ${e}`)),console.log(o.cyan(" 4. Deploy to cloud:")),console.log(o.cyan(` zibby deploy ${e}
56
- `))}catch(g){i.fail(" Scaffold failed"),console.log(o.red(`
57
- ${g.message}
58
- `)),process.exit(1)}}export{W as generateWorkflowCommand};
52
+ `)),process.exit(1));let t=process.cwd(),a=".zibby/workflows";try{let s=await g(t);console.log(o.gray(` \u{1F4CB} Loaded config: workflows path = ${s?.paths?.workflows||"(not set)"}`)),a=s?.paths?.workflows||".zibby/workflows"}catch(s){console.log(o.yellow(` \u26A0\uFE0F Could not load .zibby.config.mjs: ${s.message}`)),console.log(o.gray(` Using default path: ${a}`))}let l=n(t,a,e),c=n(l,"nodes");b(l)&&(console.log(o.red(`
53
+ Workflow already exists: ${a}/${e}/`)),console.log(o.gray(` Choose a different name or delete the existing folder.
54
+ `)),process.exit(1));let m=j(e),p=x(` Scaffolding workflow "${e}"...`).start();try{await d(n(t,a),{recursive:!0}),await d(c,{recursive:!0}),await Promise.all([i(n(l,"graph.mjs"),z(m,e)),i(n(c,"index.mjs"),N()),i(n(c,"example.mjs"),C()),i(n(l,"workflow.json"),S(e,m)),i(n(l,"package.json"),v())]),p.succeed(` Scaffolded ${o.bold(e)}`),console.log(o.green(`
55
+ Created:`)),console.log(o.white(` ${a}/${e}/`)),console.log(o.gray(` graph.mjs ${m} (entry)`)),console.log(o.gray(" nodes/index.mjs barrel export")),console.log(o.gray(" nodes/example.mjs starter node (prompt + schema)")),console.log(o.gray(" workflow.json manifest")),console.log(o.gray(" package.json dependencies (@zibby/core)")),console.log(o.white(`
56
+ Next steps:`)),console.log(o.cyan(` 1. Edit nodes in ${a}/${e}/nodes/`)),console.log(o.cyan(" 2. Wire them in graph.mjs")),console.log(o.cyan(" 3. Test locally:")),console.log(o.cyan(` zibby start ${e}`)),console.log(o.cyan(" 4. Deploy to cloud:")),console.log(o.cyan(` zibby deploy ${e}
57
+ `))}catch(s){p.fail(" Scaffold failed"),console.log(o.red(`
58
+ ${s.message}
59
+ `)),process.exit(1)}}export{P as generateWorkflowCommand};
@@ -0,0 +1,19 @@
1
+ import{readdir as A,stat as D}from"fs/promises";import{existsSync as w}from"fs";import{join as g}from"path";import n from"chalk";import z from"dotenv";import{existsSync as E}from"fs";import{join as j}from"path";import{pathToFileURL as B}from"url";async function b(e){let r=j(e,".zibby.config.mjs");if(!E(r))throw new Error(".zibby.config.mjs not found");try{let t=await import(B(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 V,readFileSync as N,writeFileSync as W}from"fs";import{homedir as k}from"os";import{join as y}from"path";function $(){return process.env.ZIBBY_CONFIG_DIR||y(k(),".zibby")}function P(){return y($(),"config.json")}var C=y(k(),".zibby"),J=y(C,"config.json");function R(){try{let e=P();if(x(e)){let r=N(e,"utf-8");return JSON.parse(r)}}catch{}return{}}function _(){return R().sessionToken||null}z.config();async function T(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
+ No workflows found in ${t}/`)),console.log(n.gray(` Create one with: zibby g workflow <name>
3
+ `)),[]);try{let p=await A(d),l=[];for(let s of p){let i=g(d,s);if(!(await D(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
+ No workflows found in ${t}/`)),console.log(n.gray(` Create one with: zibby g workflow <name>
5
+ `)),[];console.log(n.bold.cyan(`
6
+ Local Workflows (${t})
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
+ 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(p){if(e.quiet)return[];console.log(n.red(`
10
+ Error reading workflows: ${p.message}
11
+ `)),process.exit(1)}}async function to(e={}){let r=await T({...e,quiet:!0}),t=[],d=_(),p=e.apiKey||process.env.ZIBBY_API_KEY,l=d||p;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();for(let a of v)t.push({uuid:a.uuid,name:a.workflowType,projectId:m.projectId,projectName:m.name||m.projectId,version:a.version||0,isDefault:a.isDefault!==!1&&!a.graphJson,nodes:a.graphJson?JSON.parse(a.graphJson).nodes?.length:0,updatedAt:a.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",status:o.isDefault?"default":"custom",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",status:c.hasGraph?"ready":"incomplete",nodes:"-",version:"-",hasLocal:!0});if(s.length===0){console.log(`
12
+ No workflows found
13
+ `),console.log(` Create one with: zibby g workflow <name>
14
+ `);return}console.log(`
15
+ Workflows
16
+ `),console.log(" ".padEnd(130,"-")),console.log(`${" UUID".padEnd(40)+"Name".padEnd(20)+"Project".padEnd(20)+"Source".padEnd(16)+"Status".padEnd(15)+"Nodes".padEnd(8)}Ver`),console.log(" ".padEnd(134,"-"));for(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)}${o.status.padEnd(15)}${String(o.nodes).padEnd(8)}${String(o.version)}`)}console.log(" ".padEnd(134,"-")),console.log(`
17
+ Total: ${s.length} workflow${s.length===1?"":"s"}
18
+ `),console.log(" Commands:"),console.log(" zibby start <name> Test locally"),console.log(" zibby deploy <name> Deploy to cloud (generates UUID)"),console.log(" zibby logs <uuid> View remote workflow logs"),l||console.log(`
19
+ Set ZIBBY_API_KEY to see remote workflows`),console.log("")}export{to as listAllWorkflowsCommand,T as listLocalWorkflowsCommand};
@@ -1,21 +1,30 @@
1
- import o from"chalk";import{getSessionToken as k}from"../../config/config.js";import h from"dotenv";h.config();const w="https://logs.workflows.zibby.app";function j(e){const r=e.apiKey||process.env.ZIBBY_API_KEY||k();r||(console.log(o.red(`
1
+ import o from"chalk";import{readFileSync as k,existsSync as h}from"fs";import{homedir as x}from"os";import{join as j}from"path";var b="https://logs.workflows.zibby.app";function S(n){let r=j(x(),".zibby","config.json");h(r)||(console.log(o.red(`
2
2
  Not authenticated`)),console.log(o.gray(` Run: zibby login
3
- `)),process.exit(1));const t=e.project||process.env.ZIBBY_PROJECT_ID;return t||(console.log(o.red(`
4
- --project or ZIBBY_PROJECT_ID is required`)),console.log(o.gray(` Example: zibby logs <jobId> --project <id>
5
- `)),process.exit(1)),{token:r,projectId:t}}function $(e){return new Date(e).toISOString().replace("T"," ").replace("Z","")}function I(e){return e==="running"?o.yellow(e):e==="completed"?o.green(e):o.red(e||"unknown")}function b(e){return e?.length>16?e.slice(0,16):e}async function p(e,r){const t=await fetch(e,{headers:{Authorization:`Bearer ${r}`}});if(!t.ok){const i=await t.text();throw new Error(`API ${t.status}: ${i}`)}return t.json()}async function x(e,r,t,i){if(e)return e;const g=r.workflow;g||(console.log(o.red(`
6
- Job ID or --workflow is required`)),console.log(o.gray(" Usage: zibby logs <jobId> --project <id>")),console.log(o.gray(" zibby logs --workflow ticket-triage --project <id>")),console.log(o.gray(` zibby logs --workflow ticket-triage --all --project <id>
7
- `)),process.exit(1));const m=new URLSearchParams({workflow:g,limit:"10"}),{jobs:l}=await p(`${w}/jobs/${i}?${m}`,t);(!l||l.length===0)&&(console.log(o.yellow(`
8
- No jobs found for workflow "${g}".`)),process.exit(0)),console.log(o.gray(`
9
- Recent runs for ${o.cyan(g)}:
10
- `));for(const f of l.slice(0,5))console.log(o.gray(` ${b(f.jobId)} ${I(f.status)} ${f.createdAt||""}`));const a=l[0];return console.log(o.gray(`
11
- Tailing latest: ${o.cyan(b(a.jobId))}
12
- `)),a.jobId}async function T({token:e,projectId:r,jobId:t,follow:i,limit:g}){const m=`${w}/logs/${r}/${t}`;let l=null,a=0;const f=new Set;for(console.log(o.gray(` Tailing logs for job ${o.cyan(b(t))}...`)),console.log(i?o.gray(` Press Ctrl+C to stop.
13
- `):"");;)try{const u=new URLSearchParams({limit:String(g)});l&&u.set("nextToken",l);const n=await p(`${m}?${u}`,e);n.message&&n.lines?.length===0&&a===0&&console.log(o.gray(` ${n.message}`));for(const s of n.lines||[]){const d=`${s.timestamp}:${s.message}`;if(f.has(d))continue;f.add(d);const y=o.gray($(s.timestamp));console.log(`${y} ${s.message.replace(/\n$/,"")}`)}if(a=n.lines?.length>0?0:a+1,l=n.nextForwardToken||null,n.status==="completed"||n.status==="failed"){const s=n.status==="completed"?o.green:o.red;console.log(s(`
14
- Job ${n.status}.`)),process.exit(n.status==="completed"?0:1)}if(!i){n.status&&console.log(o.gray(`
15
- Status: ${n.status}`));break}await new Promise(s=>setTimeout(s,a>5?5e3:2e3))}catch(u){if(u.name==="AbortError")break;console.error(o.red(` Error: ${u.message}`)),i||process.exit(1),await new Promise(n=>setTimeout(n,3e3))}}async function P({token:e,projectId:r,workflow:t,follow:i,limit:g}){const m=`${w}/all/${r}`;let l=null,a=0;const f=new Set;let u=null;for(console.log(o.gray(`
16
- Tailing all runs for ${o.cyan(t)}...`)),console.log(i?o.gray(` Press Ctrl+C to stop.
17
- `):"");;)try{const n=new URLSearchParams({workflow:t,limit:String(g)});l&&n.set("nextToken",l);const c=await p(`${m}?${n}`,e);c.message&&c.lines?.length===0&&a===0&&console.log(o.gray(` ${c.message}`));for(const s of c.lines||[]){const d=`${s.timestamp}:${s.jobId}:${s.message}`;if(f.has(d))continue;f.add(d),s.jobId!==u&&(u!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 ${b(s.jobId)} \u2500\u2500`)),u=s.jobId);const y=o.gray($(s.timestamp));console.log(`${y} ${s.message.replace(/\n$/,"")}`)}if(a=c.lines?.length>0?0:a+1,l=c.nextToken||null,!i){l&&console.log(o.gray(`
18
- ... more logs available. Run again or use --follow to stream.`)),c.jobCount&&console.log(o.gray(` ${c.jobCount} job(s) found.`));break}if(!c.hasRunning&&!l&&a>2){console.log(o.gray(`
19
- No running jobs. All caught up.`));break}await new Promise(s=>setTimeout(s,a>5?5e3:2e3))}catch(n){if(n.name==="AbortError")break;console.error(o.red(` Error: ${n.message}`)),i||process.exit(1),await new Promise(c=>setTimeout(c,3e3))}}async function C(e,r){const{token:t,projectId:i}=j(r),g=r.follow!==!1,m=r.lines?parseInt(r.lines,10):200;if(r.all){const a=r.workflow;return a||(console.log(o.red(`
3
+ `)),process.exit(1));let t;try{t=JSON.parse(k(r,"utf-8"))}catch{console.log(o.red(`
4
+ Config file corrupt`)),console.log(o.gray(` Run: zibby login
5
+ `)),process.exit(1)}let l=t.sessionToken;l||(console.log(o.red(`
6
+ Not authenticated`)),console.log(o.gray(` Run: zibby login
7
+ `)),process.exit(1));let c=n.project;return{token:l,projectId:c}}function p(n){return new Date(n).toISOString().replace("T"," ").replace("Z","")}function T(n){return n==="running"?o.yellow(n):n==="completed"?o.green(n):o.red(n||"unknown")}function d(n){return n?.length>16?n.slice(0,16):n}async function $(n,r){let t=await fetch(n,{headers:{Authorization:`Bearer ${r}`}});if(!t.ok){let l=await t.text();throw new Error(`API ${t.status}: ${l}`)}return t.json()}async function I(n,r,t,l){if(n)return n;l||(console.log(o.red(`
8
+ Job ID or --project is required`)),console.log(o.gray(" Usage: zibby logs <uuid>")),console.log(o.gray(` zibby logs --workflow ticket-triage --project <id>
9
+ `)),process.exit(1));let c=r.workflow;c||(console.log(o.red(`
10
+ Job ID or --workflow is required`)),console.log(o.gray(" Usage: zibby logs <uuid>")),console.log(o.gray(" zibby logs --workflow ticket-triage --project <id>")),console.log(o.gray(` zibby logs --workflow ticket-triage --all --project <id>
11
+ `)),process.exit(1));let y=new URLSearchParams({workflow:c,limit:"10"}),{jobs:a}=await $(`${b}/jobs/${l}?${y}`,t);(!a||a.length===0)&&(console.log(o.yellow(`
12
+ No jobs found for workflow "${c}".`)),process.exit(0)),console.log(o.gray(`
13
+ Recent runs for ${o.cyan(c)}:
14
+ `));for(let f of a.slice(0,5))console.log(o.gray(` ${d(f.jobId)} ${T(f.status)} ${f.createdAt||""}`));let i=a[0];return console.log(o.gray(`
15
+ Tailing latest: ${o.cyan(d(i.jobId))}
16
+ `)),i.jobId}async function P({token:n,projectId:r,workflowUuid:t,follow:l,limit:c}){console.log(o.gray(` Tailing all executions for workflow ${o.cyan(t)}...`)),console.log(o.gray(" Showing live logs from all runs (interleaved by timestamp).")),console.log(o.gray(` Press Ctrl+C to stop.
17
+ `));let y=new Set,a=new Set,i=null;for(;;)try{let f=r?`${b}/logs/${r}/${t}`:`${b}/job/${t}`,m=new URLSearchParams({limit:String(c)}),s=await $(`${f}?${m}`,n);if(s.executions)for(let e of s.executions)a.has(e.jobId)||(a.size>0&&console.log(o.yellow(`
18
+ \u26A1 New execution: ${d(e.jobId)}
19
+ `)),a.add(e.jobId));let g=[];for(let e of s.lines||[]){let u=`${e.jobId}:${e.timestamp}:${e.message}`;y.has(u)||(y.add(u),g.push(e))}g.sort((e,u)=>e.timestamp-u.timestamp);for(let e of g){let u=e.jobId||e.executionId;u!==i&&(i!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 Execution: ${d(u)} \u2500\u2500`)),i=u);let w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(!l)break;await new Promise(e=>setTimeout(e,2e3))}catch(f){if(f.name==="AbortError")break;console.error(o.red(` Error: ${f.message}`)),l||process.exit(1),await new Promise(m=>setTimeout(m,3e3))}}async function z({token:n,projectId:r,jobId:t,follow:l,limit:c}){let y=r?`${b}/logs/${r}/${t}`:`${b}/job/${t}`,a=null,i=0,f=new Set;for(console.log(o.gray(` Tailing logs for job ${o.cyan(t)}...`)),console.log(l?o.gray(` Press Ctrl+C to stop.
20
+ `):"");;)try{let m=new URLSearchParams({limit:String(c)});a&&m.set("nextToken",a);let s=await $(`${y}?${m}`,n);s.message&&s.lines?.length===0&&i===0&&console.log(o.gray(` ${s.message}`)),s.status==="starting"&&s.lines?.length===0&&i===0&&console.log(o.gray(" Container starting..."));for(let e of s.lines||[]){let u=`${e.timestamp}:${e.message}`;if(f.has(u))continue;f.add(u);let w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(i=s.lines?.length>0?0:i+1,a=s.nextForwardToken||null,s.status==="completed"||s.status==="failed"){let e=s.status==="completed"?o.green:o.red;console.log(e(`
21
+ Job ${s.status}.`)),process.exit(s.status==="completed"?0:1)}if(!l){s.status&&console.log(o.gray(`
22
+ Status: ${s.status}`));break}await new Promise(e=>setTimeout(e,i>5?5e3:2e3))}catch(m){if(m.name==="AbortError")break;console.error(o.red(` Error: ${m.message}`)),l||process.exit(1),await new Promise(s=>setTimeout(s,3e3))}}async function E({token:n,projectId:r,workflow:t,follow:l,limit:c}){let y=`${b}/all/${r}`,a=null,i=0,f=new Set,m=null;for(console.log(o.gray(`
23
+ Tailing all runs for ${o.cyan(t)}...`)),console.log(l?o.gray(` Press Ctrl+C to stop.
24
+ `):"");;)try{let s=new URLSearchParams({workflow:t,limit:String(c)});a&&s.set("nextToken",a);let g=await $(`${y}?${s}`,n);g.message&&g.lines?.length===0&&i===0&&console.log(o.gray(` ${g.message}`));for(let e of g.lines||[]){let u=`${e.timestamp}:${e.jobId}:${e.message}`;if(f.has(u))continue;f.add(u),e.jobId!==m&&(m!==null&&console.log(""),console.log(o.dim(` \u2500\u2500 ${d(e.jobId)} \u2500\u2500`)),m=e.jobId);let w=o.gray(p(e.timestamp));console.log(`${w} ${e.message.replace(/\n$/,"")}`)}if(i=g.lines?.length>0?0:i+1,a=g.nextToken||null,!l){a&&console.log(o.gray(`
25
+ ... more logs available. Run again or use --follow to stream.`)),g.jobCount&&console.log(o.gray(` ${g.jobCount} job(s) found.`));break}if(!g.hasRunning&&!a&&i>2){console.log(o.gray(`
26
+ No running jobs. All caught up.`));break}await new Promise(e=>setTimeout(e,i>5?5e3:2e3))}catch(s){if(s.name==="AbortError")break;console.error(o.red(` Error: ${s.message}`)),l||process.exit(1),await new Promise(g=>setTimeout(g,3e3))}}async function U(n,r){let{token:t,projectId:l}=S(r),c=r.follow!==!1,y=r.lines?parseInt(r.lines,10):500;if(r.all){let i=r.workflow;return i||(console.log(o.red(`
20
27
  --workflow is required with --all`)),console.log(o.gray(` Example: zibby logs --workflow ticket-triage --all --project <id>
21
- `)),process.exit(1)),P({token:t,projectId:i,workflow:a,follow:g,limit:m})}const l=await x(e,r,t,i);return T({token:t,projectId:i,jobId:l,follow:g,limit:m})}export{C as logsCommand};
28
+ `)),process.exit(1)),E({token:t,projectId:l,workflow:i,follow:c,limit:y})}if(r.tailLatest)return n||(console.log(o.red(`
29
+ Workflow UUID is required with --tail-latest`)),console.log(o.gray(` Example: zibby logs <workflowUuid> -t
30
+ `)),process.exit(1)),P({token:t,projectId:l,workflowUuid:n,follow:c,limit:y});let a=await I(n,r,t,l);return z({token:t,projectId:l,jobId:a,follow:c,limit:y})}export{U as logsCommand};
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import{mkdirSync as S,writeFileSync as C,existsSync as k}from"fs";import{join as w,dirname as b,resolve as W}from"path";import{pathToFileURL as j}from"url";const $=process.env.WORKSPACE||"/workspace";async function F(){const s=process.env.WORKFLOW_SOURCES_URL;if(!s)throw new Error("WORKFLOW_SOURCES_URL env var is required");console.log("\u{1F4E6} Fetching workflow sources via pre-signed URL\u2026");const o=await fetch(s);if(!o.ok)throw new Error(`Failed to fetch sources: ${o.status} ${o.statusText}`);const e=await o.json();if(!e.sources||typeof e.sources!="object")throw new Error('Invalid sources payload \u2014 missing "sources" map');return e}function L(s,o){const e=W(o);let t=0;for(const[r,c]of Object.entries(s)){const n=W(o,r);if(!n.startsWith(`${e}/`)&&n!==e){console.error(` \u26D4 Skipping unsafe path: ${r}`);continue}S(b(n),{recursive:!0}),C(n,c,"utf-8"),t++}return t}async function P(s,o){const e=w(s,"graph.mjs");if(!k(e))throw new Error(`graph.mjs not found at ${e}`);const t=await import(j(e).href),r=o?.entryClass,c=r&&t[r]||t.default||Object.values(t).find(n=>typeof n=="function"&&n.prototype?.buildGraph);if(!c)throw new Error("No WorkflowAgent class found in graph.mjs");return c}async function K(){const{WORKFLOW_JOB_ID:s,WORKFLOW_TYPE:o,PROJECT_ID:e,AGENT_TYPE:t,MODEL:r}=process.env;o||(console.error("\u274C Missing WORKFLOW_TYPE env var"),process.exit(1)),console.log(`
3
- \u{1F680} Zibby Custom Workflow Runner`),console.log(` Job: ${s||"local"}`),console.log(` Workflow: ${o}`),console.log(` Project: ${e||"none"}`),console.log(` Agent: ${t||"default"}`),console.log(` Model: ${r||"auto"}`),console.log("\u2500".repeat(60));const c=await F(),{sources:n,input:O,workflowType:l,version:y}=c;console.log(` Workflow v${y||"?"} \u2014 ${Object.keys(n).length} source files`);const a=w($,".zibby","workflows",l||o),R=L(n,a);console.log(` \u2705 Wrote ${R} files to ${a}`);let p={};const d=w(a,"workflow.json");if(k(d)){const{readFileSync:f}=await import("fs");p=JSON.parse(f(d,"utf-8"))}const g=await P(a,p);console.log(` \u2705 Loaded ${g.name}`);const v=Date.now(),i=new g({workflow:l||o}),h=i.buildGraph(),E={input:O||{},cwd:$,runId:s||`run-${Date.now()}`};console.log(`
4
- \u25B6 Running graph (${h.nodes?.size||"?"} nodes)\u2026
5
- `);let u;try{u=await h.run(i,E)}catch(f){console.error(`
6
- \u274C Workflow execution failed: ${f.message}`),console.error(f.stack),process.exit(1)}const m=((Date.now()-v)/1e3).toFixed(1);u?.success!==!1?console.log(`
7
- \u2705 Workflow "${l||o}" completed in ${m}s`):(console.error(`
8
- \u274C Workflow "${l||o}" failed after ${m}s`),process.exit(1)),i.onComplete&&await i.onComplete(u)}export{K as runWorkflowCommand};
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(`\u{1F4CA} 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("\u26A0\uFE0F No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`\u2705 Final status ${e} sent via ${p}`)}catch(c){console.error(`\u274C 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("\u{1F4E6} Fetching workflow sources via pre-signed URL\u2026");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("\u274C Missing WORKFLOW_TYPE env var"),process.exit(1)),console.log(`
3
+ \u{1F680} Zibby Custom Workflow Runner`),console.log(` Job: ${s||"local"}`),console.log(` Workflow: ${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(` \u2705 Wrote ${c} files to ${f}`),console.log(" \u{1F4E6} Installing dependencies...");let{execSync:T}=await import("child_process");try{T("npm install --silent --no-audit --no-fund",{cwd:f,stdio:"inherit"}),console.log(" \u2705 Dependencies installed")}catch(a){console.warn(` \u26A0\uFE0F 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(` \u2705 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
+ \u25B6 Running graph (${R.nodes?.size||"?"} nodes)\u2026
5
+ `);let g;try{g=await R.run(u,A)}catch(a){console.error(`
6
+ \u274C 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
+ \u2705 Workflow "${l||e}" completed in ${$}s`),await w("completed")):(console.error(`
8
+ \u274C 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,13 +1,13 @@
1
- import{existsSync as y}from"fs";import{readFile as j}from"fs/promises";import{join as m}from"path";import{pathToFileURL as E}from"url";import o from"chalk";import T from"ora";const W=3848;function S(e){const n=process.cwd();return m(n,".zibby","workflows",e)}async function z(e,n){const t=m(e,"graph.mjs");if(!y(t))throw new Error(`graph.mjs not found in .zibby/workflows/${n}/`);const l=await O(e,n),a=await import(E(t).href),s=l.entryClass,i=s&&a[s]||a.default||Object.values(a).find(r=>typeof r=="function"&&r.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:i,manifest:l}}async function O(e,n){const t=m(e,"workflow.json");if(!y(t))return{name:n,triggers:{api:!0}};const l=await j(t,"utf-8");return JSON.parse(l)}async function A(e,n){e||(console.log(o.red(`
1
+ import{existsSync as y}from"fs";import{readFile as j}from"fs/promises";import{join as m}from"path";import{pathToFileURL as E}from"url";import o from"chalk";import T from"ora";var W=3848;function S(e){let n=process.cwd();return m(n,".zibby","workflows",e)}async function z(e,n){let t=m(e,"graph.mjs");if(!y(t))throw new Error(`graph.mjs not found in .zibby/workflows/${n}/`);let l=await O(e,n),a=await import(E(t).href),s=l.entryClass,i=s&&a[s]||a.default||Object.values(a).find(r=>typeof r=="function"&&r.prototype?.buildGraph);if(!i)throw new Error("No WorkflowAgent class found in graph.mjs. Export a class with buildGraph() method.");return{AgentClass:i,manifest:l}}async function O(e,n){let t=m(e,"workflow.json");if(!y(t))return{name:n,triggers:{api:!0}};let l=await j(t,"utf-8");return JSON.parse(l)}async function A(e,n){e||(console.log(o.red(`
2
2
  Workflow name is required`)),console.log(o.gray(" Usage: zibby start <workflow-name>")),console.log(o.gray(` Example: zibby start ticket-triage
3
- `)),process.exit(1));const t=e.toLowerCase(),l=S(t);y(l)||(console.log(o.red(`
3
+ `)),process.exit(1));let t=e.toLowerCase(),l=S(t);y(l)||(console.log(o.red(`
4
4
  Workflow not found: .zibby/workflows/${t}/`)),console.log(o.gray(" Create one first:")),console.log(o.cyan(` zibby g workflow ${t}
5
- `)),process.exit(1));const a=T(` Loading workflow "${t}"...`).start();let s,i;try{({AgentClass:s,manifest:i}=await z(l,t)),a.succeed(` Loaded ${o.bold(i.entryClass||s.name)} (${t})`)}catch(g){a.fail(" Failed to load workflow"),console.log(o.red(`
5
+ `)),process.exit(1));let a=T(` Loading workflow "${t}"...`).start(),s,i;try{({AgentClass:s,manifest:i}=await z(l,t)),a.succeed(` Loaded ${o.bold(i.entryClass||s.name)} (${t})`)}catch(g){a.fail(" Failed to load workflow"),console.log(o.red(`
6
6
  ${g.message}
7
- `)),process.exit(1)}const r=parseInt(n.port,10)||W;let f;try{f=(await import("express")).default}catch{console.log(o.red(`
7
+ `)),process.exit(1)}let r=parseInt(n.port,10)||W,f;try{f=(await import("express")).default}catch{console.log(o.red(`
8
8
  express is required for local workflow server`)),console.log(o.gray(` npm install express
9
- `)),process.exit(1)}const w=f();w.use(f.json({limit:"1mb"})),w.get("/health",(g,d)=>{d.json({status:"ok",workflow:t,class:s.name})}),w.post("/trigger",async(g,d)=>{const c=`local-${Date.now()}`,h=g.body.input||g.body||{};console.log(o.cyan(`
10
- \u25B6 Run ${c} triggered`)),console.log(o.gray(` input: ${JSON.stringify(h).slice(0,200)}`)),d.status(202).json({runId:c,status:"running",workflow:t});try{const u=Date.now(),p=new s({workflow:t}),$=p.buildGraph(),C={input:h,cwd:process.cwd(),runId:c},k=await $.run(p,C),b=((Date.now()-u)/1e3).toFixed(1),x=k?.success!==!1;console.log(x?o.green(` \u2714 Run ${c} succeeded (${b}s)`):o.red(` \u2716 Run ${c} failed (${b}s)`)),p.onComplete&&await p.onComplete(k)}catch(u){console.log(o.red(` \u2716 Run ${c} error: ${u.message}`))}}),w.listen(r,()=>{console.log(o.bold.cyan(`
9
+ `)),process.exit(1)}let w=f();w.use(f.json({limit:"1mb"})),w.get("/health",(g,d)=>{d.json({status:"ok",workflow:t,class:s.name})}),w.post("/trigger",async(g,d)=>{let c=`local-${Date.now()}`,h=g.body.input||g.body||{};console.log(o.cyan(`
10
+ \u25B6 Run ${c} triggered`)),console.log(o.gray(` input: ${JSON.stringify(h).slice(0,200)}`)),d.status(202).json({runId:c,status:"running",workflow:t});try{let u=Date.now(),p=new s({workflow:t}),$=p.buildGraph(),C={input:h,cwd:process.cwd(),runId:c},k=await $.run(p,C),b=((Date.now()-u)/1e3).toFixed(1),x=k?.success!==!1;console.log(x?o.green(` \u2714 Run ${c} succeeded (${b}s)`):o.red(` \u2716 Run ${c} failed (${b}s)`)),p.onComplete&&await p.onComplete(k)}catch(u){console.log(o.red(` \u2716 Run ${c} error: ${u.message}`))}}),w.listen(r,()=>{console.log(o.bold.cyan(`
11
11
  Zibby Workflow Server \u2014 ${t}
12
12
  `)),console.log(o.gray(" ".padEnd(56,"-"))),console.log(o.white(` Workflow: ${o.cyan(t)}`)),console.log(o.white(` Class: ${o.cyan(s.name)}`)),console.log(o.white(` Port: ${o.cyan(r)}`)),console.log(o.gray(" ".padEnd(56,"-"))),console.log(o.white(`
13
13
  Endpoints:`)),console.log(o.gray(` GET http://localhost:${r}/health`)),console.log(o.cyan(` POST http://localhost:${r}/trigger`)),console.log(o.white(`
@@ -0,0 +1,10 @@
1
+ import g from"ora";import h from"dotenv";import{select as u}from"@inquirer/prompts";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 f(){let t;if(process.env.ZIBBY_API_URL)t=process.env.ZIBBY_API_URL;else{let e=process.env.ZIBBY_ENV||"prod";d[e]?t=d[e].apiUrl:t=d.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)`),d.prod.apiUrl):t}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${t}`),d.prod.apiUrl}}h.config();async function I(t){let e=f(),c=g("Fetching projects...").start();try{let n=await fetch(`${e}/projects`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`}});n.ok||(c.fail("Failed to fetch projects"),process.exit(1));let o=await n.json();Array.isArray(o)||(o.projects?o=o.projects:o.data&&(o=o.data)),(!o||o.length===0)&&(c.fail("No projects found"),process.exit(1)),c.succeed(`Found ${o.length} project${o.length===1?"":"s"}`),console.log("");let s=o.map(r=>({name:`${r.name||"Unnamed"} (${r.projectId||r.id})`,value:r.projectId||r.id}));return await u({message:"Select a project:",choices:s})}catch(n){c.fail(`Error: ${n.message}`),process.exit(1)}}async function y(t,e){let c=f(),n=g("Fetching deployed workflows...").start();try{let o=["analysis","implementation","run_test"],s=[];for(let l of o){let a=await fetch(`${c}/projects/${t}/workflows/${l}`,{method:"GET",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});if(a.ok){let i=await a.json();i.graph&&s.push({name:l,version:i.version||0,isDefault:i.isDefault!==!1})}}s.length===0&&(n.fail("No deployed workflows found for this project"),process.exit(1)),n.succeed(`Found ${s.length} deployed workflow${s.length===1?"":"s"}`),console.log("");let r=s.map(l=>({name:`${l.name} (v${l.version})${l.isDefault?" [default]":""}`,value:l.name}));return await u({message:"Select a workflow to trigger:",choices:r})}catch(o){n.fail(`Error: ${o.message}`),process.exit(1)}}async function B(t,e={}){let c=e.apiKey||process.env.ZIBBY_API_KEY;c||(console.log(`
2
+ Error: ZIBBY_API_KEY not set`),console.log(` Add to .env or use --api-key flag
3
+ `),process.exit(1));let n=e.project||process.env.ZIBBY_PROJECT_ID;n||(console.log(""),n=await I(c)),t||(console.log(""),t=await y(n,c));let o={};if(e.input)try{o=JSON.parse(e.input)}catch(r){console.log(`
4
+ Error: Invalid JSON in --input`),console.log(` ${r.message}
5
+ `),process.exit(1)}console.log(`
6
+ Triggering Workflow
7
+ `),console.log(" ".padEnd(60,"-")),console.log(` Workflow: ${t}`),console.log(` Project: ${n}`),Object.keys(o).length>0&&console.log(` Input: ${JSON.stringify(o).substring(0,50)}...`),e.idempotencyKey&&console.log(` Idempotency: ${e.idempotencyKey}`),console.log(" ".padEnd(60,"-")),console.log("");let s=g("Triggering workflow execution...").start();try{let r=f(),l={input:o};e.idempotencyKey&&(l.idempotencyKey=e.idempotencyKey);let a=await fetch(`${r}/projects/${n}/workflows/${t}/trigger`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify(l)});if(!a.ok){let p=await a.json().catch(()=>({}));a.status===429&&(s.fail("Quota exceeded"),console.log(`
8
+ 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)),s.fail("Trigger failed"),console.log(` Error: ${p.message||a.statusText}
9
+ `),process.exit(1)}let i=await a.json();s.succeed("Workflow triggered successfully"),console.log(""),console.log(" Job Details:"),console.log(` Job ID: ${i.jobId}`),console.log(` Status: ${i.status}`),console.log(` Version: ${i.version}`),console.log(` Triggered: ${new Date(i.triggeredAt).toLocaleString()}`),console.log(""),console.log(" Monitor execution:"),console.log(` zibby logs ${i.jobId}`),console.log(` zibby logs --workflow ${t}`),console.log("")}catch(r){s.fail("Trigger failed"),console.log(` Error: ${r.message}
10
+ `),process.exit(1)}}export{B as triggerWorkflowCommand};
@@ -0,0 +1 @@
1
+ import{existsSync as t}from"fs";import{join as n}from"path";import{pathToFileURL as e}from"url";async function s(i){let r=n(i,".zibby.config.mjs");if(!t(r))throw new Error(".zibby.config.mjs not found");try{let o=await import(e(r).href);return o.default||o}catch(o){throw new Error(`Failed to load .zibby.config.mjs: ${o.message}`,{cause:o})}}export{s as loadUserConfig};
@@ -1 +1 @@
1
- import{existsSync as i,mkdirSync as l,readFileSync as x,writeFileSync as p}from"fs";import{homedir as c}from"os";import{join as t}from"path";function s(){return process.env.ZIBBY_CONFIG_DIR||t(c(),".zibby")}function f(){return t(s(),"config.json")}const u=t(c(),".zibby"),y=t(u,"config.json");function m(){const n=s();i(n)||l(n,{recursive:!0})}function e(){try{const n=f();if(i(n)){const o=x(n,"utf-8");return JSON.parse(o)}}catch{}return{}}function r(n){m(),p(f(),JSON.stringify(n,null,2))}function g(){return e().sessionToken||null}function a(n){const o=e();o.sessionToken=n,r(o)}function d(){return e().user||null}function U(n){const o=e();o.user=n,r(o)}function I(){return g()!==null}function P(){const n=e();delete n.sessionToken,delete n.user,delete n.mem0ProxyUrl,r(n)}function S(){return e().proxyUrl||null}function v(n){const o=e();o.proxyUrl=n,r(o)}function C(){return e().mem0ProxyUrl||null}function j(n){const o=e();o.mem0ProxyUrl=n,r(o)}function F(){return e().projects||[]}function k(n){const o=e();o.projects=n,r(o)}var b={loadConfig:e,saveConfig:r,getSessionToken:g,saveSessionToken:a,getUserInfo:d,saveUserInfo:U,isLoggedIn:I,clearSession:P,getProxyUrl:S,saveProxyUrl:v,getMem0ProxyUrl:C,saveMem0ProxyUrl:j,getProjects:F,saveProjects:k,CONFIG_DIR:u,CONFIG_FILE:y};export{P as clearSession,b as default,C as getMem0ProxyUrl,F as getProjects,S as getProxyUrl,g as getSessionToken,d as getUserInfo,I as isLoggedIn,e as loadConfig,r as saveConfig,j as saveMem0ProxyUrl,k as saveProjects,v as saveProxyUrl,a as saveSessionToken,U as saveUserInfo};
1
+ import{existsSync as i,mkdirSync as l,readFileSync as x,writeFileSync as p}from"fs";import{homedir as c}from"os";import{join as t}from"path";function s(){return process.env.ZIBBY_CONFIG_DIR||t(c(),".zibby")}function f(){return t(s(),"config.json")}var u=t(c(),".zibby"),y=t(u,"config.json");function m(){let n=s();i(n)||l(n,{recursive:!0})}function e(){try{let n=f();if(i(n)){let o=x(n,"utf-8");return JSON.parse(o)}}catch{}return{}}function r(n){m(),p(f(),JSON.stringify(n,null,2))}function g(){return e().sessionToken||null}function a(n){let o=e();o.sessionToken=n,r(o)}function d(){return e().user||null}function U(n){let o=e();o.user=n,r(o)}function I(){return g()!==null}function P(){let n=e();delete n.sessionToken,delete n.user,delete n.mem0ProxyUrl,r(n)}function S(){return e().proxyUrl||null}function v(n){let o=e();o.proxyUrl=n,r(o)}function C(){return e().mem0ProxyUrl||null}function j(n){let o=e();o.mem0ProxyUrl=n,r(o)}function F(){return e().projects||[]}function k(n){let o=e();o.projects=n,r(o)}var b={loadConfig:e,saveConfig:r,getSessionToken:g,saveSessionToken:a,getUserInfo:d,saveUserInfo:U,isLoggedIn:I,clearSession:P,getProxyUrl:S,saveProxyUrl:v,getMem0ProxyUrl:C,saveMem0ProxyUrl:j,getProjects:F,saveProjects:k,CONFIG_DIR:u,CONFIG_FILE:y};export{P as clearSession,b as default,C as getMem0ProxyUrl,F as getProjects,S as getProxyUrl,g as getSessionToken,d as getUserInfo,I as isLoggedIn,e as loadConfig,r as saveConfig,j as saveMem0ProxyUrl,k as saveProjects,v as saveProxyUrl,a as saveSessionToken,U as saveUserInfo};
@@ -1 +1 @@
1
- const n={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 s(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{const r=process.env.ZIBBY_ENV||"prod";n[r]?o=n[r].apiUrl:o=n.prod.apiUrl}try{const r=new URL(o);return r.protocol!=="http:"&&r.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${r.protocol} (only http/https allowed)`),n.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),n.prod.apiUrl}}function c(){if(process.env.ZIBBY_ACCOUNT_API_URL)return process.env.ZIBBY_ACCOUNT_API_URL;const o=process.env.ZIBBY_ENV||"prod";return(n[o]||n.prod).accountApiUrl}function l(){const o=process.env.ZIBBY_ENV||"prod";return n[o]||n.prod}function i(){let o;if(process.env.ZIBBY_FRONTEND_URL)o=process.env.ZIBBY_FRONTEND_URL;else{const r=process.env.ZIBBY_ENV||"prod";n[r]?o=n[r].frontendUrl:o=n.prod.frontendUrl}try{const r=new URL(o);if(r.protocol!=="http:"&&r.protocol!=="https:")return console.error(`\u26A0\uFE0F Invalid frontend URL protocol: ${r.protocol} (only http/https allowed)`),n.local.frontendUrl;if(process.env.NODE_ENV==="production"||process.env.ZIBBY_ENV==="prod"){const p=["zibby.app","studio.zibby.app","studio-staging.zibby.app"],t=r.hostname;if(!p.some(e=>t===e||t.endsWith(`.${e}`))&&!t.includes("localhost")&&t!=="127.0.0.1")return console.error(`\u26A0\uFE0F Untrusted frontend URL in production: ${t}`),"https://studio.zibby.app"}return o}catch{return console.error(`\u26A0\uFE0F Invalid frontend URL: ${o}`),n.local.frontendUrl}}export{n as ENVIRONMENTS,c as getAccountApiUrl,s as getApiUrl,l as getCurrentEnvironment,i as getFrontendUrl};
1
+ var n={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 l(){let o;if(process.env.ZIBBY_API_URL)o=process.env.ZIBBY_API_URL;else{let r=process.env.ZIBBY_ENV||"prod";n[r]?o=n[r].apiUrl:o=n.prod.apiUrl}try{let r=new URL(o);return r.protocol!=="http:"&&r.protocol!=="https:"?(console.error(`\u26A0\uFE0F Invalid API URL protocol: ${r.protocol} (only http/https allowed)`),n.prod.apiUrl):o}catch{return console.error(`\u26A0\uFE0F Invalid API URL: ${o}`),n.prod.apiUrl}}function i(){if(process.env.ZIBBY_ACCOUNT_API_URL)return process.env.ZIBBY_ACCOUNT_API_URL;let o=process.env.ZIBBY_ENV||"prod";return(n[o]||n.prod).accountApiUrl}function d(){let o=process.env.ZIBBY_ENV||"prod";return n[o]||n.prod}function a(){let o;if(process.env.ZIBBY_FRONTEND_URL)o=process.env.ZIBBY_FRONTEND_URL;else{let r=process.env.ZIBBY_ENV||"prod";n[r]?o=n[r].frontendUrl:o=n.prod.frontendUrl}try{let r=new URL(o);if(r.protocol!=="http:"&&r.protocol!=="https:")return console.error(`\u26A0\uFE0F Invalid frontend URL protocol: ${r.protocol} (only http/https allowed)`),n.local.frontendUrl;if(process.env.NODE_ENV==="production"||process.env.ZIBBY_ENV==="prod"){let p=["zibby.app","studio.zibby.app","studio-staging.zibby.app"],t=r.hostname;if(!p.some(e=>t===e||t.endsWith(`.${e}`))&&!t.includes("localhost")&&t!=="127.0.0.1")return console.error(`\u26A0\uFE0F Untrusted frontend URL in production: ${t}`),"https://studio.zibby.app"}return o}catch{return console.error(`\u26A0\uFE0F Invalid frontend URL: ${o}`),n.local.frontendUrl}}export{n as ENVIRONMENTS,i as getAccountApiUrl,l as getApiUrl,d as getCurrentEnvironment,a as getFrontendUrl};
package/dist/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {
7
- "zibby": "./bin/zibby.js"
7
+ "zibby": "./dist/bin/zibby.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "node ../scripts/build.mjs --extra-dirs bin",
@@ -52,8 +52,8 @@
52
52
  "ws": "^8.20.0"
53
53
  },
54
54
  "files": [
55
- "bin/",
56
- "src/",
55
+ "dist/bin/",
56
+ "dist/",
57
57
  "README.md",
58
58
  "LICENSE"
59
59
  ],
@@ -1,3 +1,3 @@
1
- import{existsSync as a,readFileSync as f,writeFileSync as b,mkdirSync as h}from"fs";import{join as i}from"path";import{homedir as u}from"os";const m={cursor:{envVar:"CURSOR_API_KEY",label:"Cursor API Key",url:"https://cursor.com/settings"},claude:{envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com/settings/keys"},codex:{envVar:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com/api-keys"},gemini:{envVar:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com/app/apikey"}};function v(){return i(u(),".zibby","config.json")}function A(){try{const n=v();return a(n)?JSON.parse(f(n,"utf-8")):{}}catch{return{}}}function V(n,r){const o=i(u(),".zibby");h(o,{recursive:!0});const t=v(),e=A(),s=r?m[r]:null;s&&((!e.agentKeys||typeof e.agentKeys!="object")&&(e.agentKeys={}),e.agentKeys[s.envVar]=String(n).trim()),delete e.agentApiKey,b(t,`${JSON.stringify(e,null,2)}
2
- `,"utf-8")}function I(n){const r=[i(n,".zibby.config.mjs"),i(u(),".zibby.config.mjs")];for(const o of r)if(a(o))try{const t=f(o,"utf-8");for(const e of["cursor","claude","codex","gemini"])if(new RegExp(`agent\\s*:\\s*\\{[^}]*${e}\\s*:`,"s").test(t))return e}catch{}return null}function _(n){const r=n||process.cwd(),o=I(r);if(!o)return;const t=m[o];if(!t||process.env[t.envVar])return;const e=[i(r,".env.local"),i(r,".env")];for(const l of e)if(a(l))try{for(const d of f(l,"utf-8").split(`
3
- `)){const c=d.trim();if(c.startsWith("#")||!c.includes("="))continue;const y=c.indexOf("="),K=c.slice(0,y).trim(),g=c.slice(y+1).trim();if(K===t.envVar&&g){process.env[t.envVar]=g;return}}}catch{}const p=A().agentKeys?.[t.envVar];p&&(process.env[t.envVar]=p)}export{m as AGENT_KEY_MAP,_ as bootstrapAgentEnv,I as detectAgentType,A as readGlobalConfig,V as saveAgentApiKey};
1
+ import{existsSync as a,readFileSync as f,writeFileSync as b,mkdirSync as h}from"fs";import{join as i}from"path";import{homedir as u}from"os";var m={cursor:{envVar:"CURSOR_API_KEY",label:"Cursor API Key",url:"https://cursor.com/settings"},claude:{envVar:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com/settings/keys"},codex:{envVar:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com/api-keys"},gemini:{envVar:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com/app/apikey"}};function v(){return i(u(),".zibby","config.json")}function A(){try{let n=v();return a(n)?JSON.parse(f(n,"utf-8")):{}}catch{return{}}}function V(n,r){let o=i(u(),".zibby");h(o,{recursive:!0});let t=v(),e=A(),s=r?m[r]:null;s&&((!e.agentKeys||typeof e.agentKeys!="object")&&(e.agentKeys={}),e.agentKeys[s.envVar]=String(n).trim()),delete e.agentApiKey,b(t,`${JSON.stringify(e,null,2)}
2
+ `,"utf-8")}function I(n){let r=[i(n,".zibby.config.mjs"),i(u(),".zibby.config.mjs")];for(let o of r)if(a(o))try{let t=f(o,"utf-8");for(let e of["cursor","claude","codex","gemini"])if(new RegExp(`agent\\s*:\\s*\\{[^}]*${e}\\s*:`,"s").test(t))return e}catch{}return null}function _(n){let r=n||process.cwd(),o=I(r);if(!o)return;let t=m[o];if(!t||process.env[t.envVar])return;let e=[i(r,".env.local"),i(r,".env")];for(let l of e)if(a(l))try{for(let d of f(l,"utf-8").split(`
3
+ `)){let c=d.trim();if(c.startsWith("#")||!c.includes("="))continue;let y=c.indexOf("="),K=c.slice(0,y).trim(),g=c.slice(y+1).trim();if(K===t.envVar&&g){process.env[t.envVar]=g;return}}}catch{}let p=A().agentKeys?.[t.envVar];p&&(process.env[t.envVar]=p)}export{m as AGENT_KEY_MAP,_ as bootstrapAgentEnv,I as detectAgentType,A as readGlobalConfig,V as saveAgentApiKey};
@@ -1,3 +1,3 @@
1
- import{existsSync as l,mkdirSync as F,readFileSync as S,readdirSync as g,unlinkSync as p,writeFileSync as d}from"fs";import{join as f}from"path";import{execSync as N}from"child_process";import{DEFAULT_OUTPUT_BASE as P}from"@zibby/core";function a(t){return t?.paths?.output||P}function m(t,r,i){return f(t,r,`.zibby-chat-run-pids-${i}.json`)}function b(t,r,i){const e=m(t,r,i);if(!l(e))return[];try{const n=JSON.parse(S(e,"utf8"));return(Array.isArray(n?.pids)?n.pids:[]).map(o=>Number(o)).filter(o=>Number.isFinite(o)&&o>0)}catch{return[]}}function C(t,r,i,e={}){const n=Number(r),s=Number(i);if(!Number.isFinite(n)||n<=0||!Number.isFinite(s)||s<=0)return;const o=a(e),c=f(t,o);F(c,{recursive:!0});const u=b(t,o,n);u.includes(s)||u.push(s),d(m(t,o,n),`${JSON.stringify({v:1,pids:u})}
2
- `,"utf8")}function R(t,r,i,e={}){const n=Number(r),s=Number(i);if(!Number.isFinite(n)||n<=0||!Number.isFinite(s)||s<=0)return;const o=a(e),c=m(t,o,n);if(!l(c))return;const u=b(t,o,n).filter(h=>h!==s);if(u.length===0)try{p(c)}catch{}else d(c,`${JSON.stringify({v:1,pids:u})}
3
- `,"utf8")}function k(t){const r=Number(t);if(!Number.isFinite(r)||r<=0)return[];try{const i=N(`pgrep -P ${r}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:524288}).trim();return i?i.split(/\n/).map(e=>parseInt(e.trim(),10)).filter(e=>Number.isFinite(e)&&e>0):[]}catch{return[]}}function y(t,r){const i=Number(t);if(!Number.isFinite(i)||i<=0)return;const e=new Set;function n(s){if(!e.has(s)){e.add(s);for(const o of k(s))n(o);try{process.kill(s,r)}catch{}}}n(i)}function x(t){const r=Number(t);if(!(!Number.isFinite(r)||r<=0))try{N(`taskkill /PID ${r} /T /F`,{stdio:"ignore",windowsHide:!0})}catch{}}function T(t){const r=Number(t);if(!Number.isFinite(r)||r<=0)return;if(process.platform==="win32"){x(r);return}y(r,"SIGTERM");const i=setTimeout(()=>{y(r,"SIGKILL")},800);typeof i.unref=="function"&&i.unref()}function U(t,r,i={}){const e=Number(r);if(!Number.isFinite(e)||e<=0)return;const n=a(i),s=m(t,n,e),o=b(t,n,e);for(const c of o)c!==process.pid&&T(c);try{l(s)&&p(s)}catch{}}function A(t){try{return process.kill(t,0),!0}catch{return!1}}const I=/^\.zibby-chat-run-pids-(\d+)\.json$/;function w(t,r={}){const i=a(r),e=f(t,i);let n;try{n=g(e)}catch{return}for(const s of n){const o=I.exec(s);if(!o)continue;const c=Number(o[1]);if(!(!Number.isFinite(c)||c<=0)&&!A(c))try{p(f(e,s))}catch{}}}export{w as cleanupStalePidFiles,U as killAllChatOrchestratedRuns,T as killPidTreeBestEffort,C as registerChatOrchestratedRun,R as unregisterChatOrchestratedRun};
1
+ import{existsSync as l,mkdirSync as F,readFileSync as S,readdirSync as g,unlinkSync as p,writeFileSync as N}from"fs";import{join as f}from"path";import{execSync as y}from"child_process";import{DEFAULT_OUTPUT_BASE as P}from"@zibby/core";function a(t){return t?.paths?.output||P}function m(t,r,i){return f(t,r,`.zibby-chat-run-pids-${i}.json`)}function b(t,r,i){let e=m(t,r,i);if(!l(e))return[];try{let n=JSON.parse(S(e,"utf8"));return(Array.isArray(n?.pids)?n.pids:[]).map(o=>Number(o)).filter(o=>Number.isFinite(o)&&o>0)}catch{return[]}}function C(t,r,i,e={}){let n=Number(r),s=Number(i);if(!Number.isFinite(n)||n<=0||!Number.isFinite(s)||s<=0)return;let o=a(e),c=f(t,o);F(c,{recursive:!0});let u=b(t,o,n);u.includes(s)||u.push(s),N(m(t,o,n),`${JSON.stringify({v:1,pids:u})}
2
+ `,"utf8")}function R(t,r,i,e={}){let n=Number(r),s=Number(i);if(!Number.isFinite(n)||n<=0||!Number.isFinite(s)||s<=0)return;let o=a(e),c=m(t,o,n);if(!l(c))return;let u=b(t,o,n).filter(h=>h!==s);if(u.length===0)try{p(c)}catch{}else N(c,`${JSON.stringify({v:1,pids:u})}
3
+ `,"utf8")}function k(t){let r=Number(t);if(!Number.isFinite(r)||r<=0)return[];try{let i=y(`pgrep -P ${r}`,{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:524288}).trim();return i?i.split(/\n/).map(e=>parseInt(e.trim(),10)).filter(e=>Number.isFinite(e)&&e>0):[]}catch{return[]}}function d(t,r){let i=Number(t);if(!Number.isFinite(i)||i<=0)return;let e=new Set;function n(s){if(!e.has(s)){e.add(s);for(let o of k(s))n(o);try{process.kill(s,r)}catch{}}}n(i)}function x(t){let r=Number(t);if(!(!Number.isFinite(r)||r<=0))try{y(`taskkill /PID ${r} /T /F`,{stdio:"ignore",windowsHide:!0})}catch{}}function T(t){let r=Number(t);if(!Number.isFinite(r)||r<=0)return;if(process.platform==="win32"){x(r);return}d(r,"SIGTERM");let i=setTimeout(()=>{d(r,"SIGKILL")},800);typeof i.unref=="function"&&i.unref()}function U(t,r,i={}){let e=Number(r);if(!Number.isFinite(e)||e<=0)return;let n=a(i),s=m(t,n,e),o=b(t,n,e);for(let c of o)c!==process.pid&&T(c);try{l(s)&&p(s)}catch{}}function A(t){try{return process.kill(t,0),!0}catch{return!1}}var I=/^\.zibby-chat-run-pids-(\d+)\.json$/;function w(t,r={}){let i=a(r),e=f(t,i),n;try{n=g(e)}catch{return}for(let s of n){let o=I.exec(s);if(!o)continue;let c=Number(o[1]);if(!(!Number.isFinite(c)||c<=0)&&!A(c))try{p(f(e,s))}catch{}}}export{w as cleanupStalePidFiles,U as killAllChatOrchestratedRuns,T as killPidTreeBestEffort,C as registerChatOrchestratedRun,R as unregisterChatOrchestratedRun};
@@ -1 +1 @@
1
- async function s(n,i){const t=process.env.CONTEXT_PRESIGNED_URL;if(!t)throw new Error("CONTEXT_PRESIGNED_URL env var is required");console.log("\u{1F4E6} Fetching execution context via pre-signed URL");const o=await fetch(t);if(!o.ok)throw new Error(`Failed to fetch execution context: ${o.status}`);const 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||[]}}export{s as fetchExecutionContext};
1
+ async function s(n,i){let t=process.env.CONTEXT_PRESIGNED_URL;if(!t)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(t);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||[]}}export{s as fetchExecutionContext};
@@ -1 +1 @@
1
- import{SQSClient as _,SendMessageCommand as u}from"@aws-sdk/client-sqs";let E=null;function O(){return E||(E=new _({region:process.env.AWS_REGION||"ap-southeast-2"})),E}async function $(c,e,s,o){const{EXECUTION_ID:t,SQS_AUTH_TOKEN:r,PROGRESS_API_URL:n,PROGRESS_QUEUE_URL:S,PROJECT_API_TOKEN:l}=o;if(!t)return;const 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){const{EXECUTION_ID:o,SQS_AUTH_TOKEN:t,PROGRESS_API_URL:r,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:S}=c;if(!o||!s)return;const l=JSON.stringify(s).length;console.log(`\u{1F4E6} Sending artifact: ${e} (${(l/1024).toFixed(1)}KB)`);const 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(`\u2705 Artifact ${e} sent via ${d} (payload=${(i/1024).toFixed(1)}KB, value=${(l/1024).toFixed(1)}KB)`)}catch(g){console.error(`\u274C 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}){const{EXECUTION_ID:o,SQS_AUTH_TOKEN:t,PROGRESS_API_URL:r,PROGRESS_QUEUE_URL:n,PROJECT_API_TOKEN:S}=c;if(!o)return;const 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(`\u{1F4CA} Sending final status: ${e} via ${a} (${(d/1024).toFixed(1)}KB)`);try{if(r)await f(r,o,l,S);else if(n){const i=["completed","failed","insufficient_context","blocked"].includes(e)?"execution_completed":"progress_update";await p(n,o,l,i)}else{console.warn("\u26A0\uFE0F No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`\u2705 Final status ${e} sent via ${a}`)}catch(i){console.error(`\u274C 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){const t=`${c}/${e}/progress`,r={"Content-Type":"application/json"};o&&(r.Authorization=`Bearer ${o}`);const n=await fetch(t,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok){const S=await n.text();throw new Error(`HTTP ${n.status}: ${S}`)}}async function p(c,e,s,o="progress_update"){const 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};
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(`\u{1F4E6} 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(`\u2705 Artifact ${e} sent via ${d} (payload=${(i/1024).toFixed(1)}KB, value=${(l/1024).toFixed(1)}KB)`)}catch(g){console.error(`\u274C 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(`\u{1F4CA} 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("\u26A0\uFE0F No transport configured for final status \u2014 neither PROGRESS_API_URL nor PROGRESS_QUEUE_URL set");return}console.log(`\u2705 Final status ${e} sent via ${a}`)}catch(i){console.error(`\u274C 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};
@@ -1 +1 @@
1
- import{createWriteStream as l,mkdirSync as d}from"fs";import{join as p,isAbsolute as w}from"path";const m="studio-cli.log";function a(t,o){if(!t||typeof t!="string")return null;const r=t.trim();return r?w(r)?r:p(o,r):null}function S(t){if(!t)return()=>{};d(t,{recursive:!0});const o=p(t,m),r=l(o,{flags:"a"}),e=process.stdout.write.bind(process.stdout),s=process.stderr.write.bind(process.stderr),i=f=>function(u,n,c){typeof n=="function"&&(c=n,n=void 0);try{Buffer.isBuffer(u)?r.write(u):r.write(String(u),n||"utf8")}catch{}return f(u,n,c)};return process.stdout.write=i(e),process.stderr.write=i(s),()=>{process.stdout.write=e,process.stderr.write=s;try{r.end()}catch{}}}function C(t,o,r){let e=null;function s(i){if(!e&&i?.sessionPath){const f=a(i.sessionPath,o);f&&(e=S(f))}typeof t=="function"&&t(i)}return s.dispose=()=>{typeof e=="function"&&(e(),e=null)},s}export{C as composePipelineProgressWithStudioCliLog,S as startStudioCliLogMirror};
1
+ import{createWriteStream as l,mkdirSync as d}from"fs";import{join as p,isAbsolute as w}from"path";var m="studio-cli.log";function a(t,o){if(!t||typeof t!="string")return null;let r=t.trim();return r?w(r)?r:p(o,r):null}function S(t){if(!t)return()=>{};d(t,{recursive:!0});let o=p(t,m),r=l(o,{flags:"a"}),e=process.stdout.write.bind(process.stdout),s=process.stderr.write.bind(process.stderr),i=f=>function(u,n,c){typeof n=="function"&&(c=n,n=void 0);try{Buffer.isBuffer(u)?r.write(u):r.write(String(u),n||"utf8")}catch{}return f(u,n,c)};return process.stdout.write=i(e),process.stderr.write=i(s),()=>{process.stdout.write=e,process.stderr.write=s;try{r.end()}catch{}}}function C(t,o,r){let e=null;function s(i){if(!e&&i?.sessionPath){let f=a(i.sessionPath,o);f&&(e=S(f))}typeof t=="function"&&t(i)}return s.dispose=()=>{typeof e=="function"&&(e(),e=null)},s}export{C as composePipelineProgressWithStudioCliLog,S as startStudioCliLogMirror};
@@ -1,7 +1,7 @@
1
- import i from"os";import a from"path";import{existsSync as m,readFileSync as S,readdirSync as h,createWriteStream as g,mkdirSync as x,rmSync as I,unlinkSync as Z}from"fs";import{execFileSync as b}from"child_process";import{createInterface as v}from"readline";import l from"chalk";const A=process.env.ZIBBY_STUDIO_CDN||"https://dl.zibby.app",n=a.join(i.homedir(),".zibby","studio");function w(){const t=i.platform(),o=i.arch();if(t==="darwin"&&o==="arm64")return{archive:"Zibby Studio-mac-arm64.zip",label:"macOS (Apple Silicon)"};if(t==="darwin")return{archive:"Zibby Studio-mac-x64.zip",label:"macOS (Intel)"};if(t==="win32"&&o==="arm64")return{archive:"Zibby Studio-win-arm64.zip",label:"Windows (ARM)"};if(t==="win32")return{archive:"Zibby Studio-win-x64.zip",label:"Windows (x64)"};if(t==="linux"&&o==="arm64")return{archive:"Zibby Studio-arm64.AppImage",label:"Linux (ARM64)"};if(t==="linux")return{archive:"Zibby Studio-1.0.0.AppImage",label:"Linux (x64)"};throw new Error(`Unsupported platform: ${t} ${o}`)}function $(){const{archive:t}=w();return`${A}/download/latest/${encodeURIComponent(t)}`}function z(t){const o=v({input:process.stdin,output:process.stdout});return new Promise(e=>{o.question(t,u=>{o.close(),e(u.trim().toLowerCase())})})}async function C(){const{label:t}=w();console.log(""),console.log(l.cyan(" Zibby Studio is not installed.")),console.log(l.gray(` Platform: ${t}`)),console.log("");const o=await z(l.white(" Download and install Zibby Studio? (Y/n): "));return o&&o!=="y"&&o!=="yes"?(console.log(l.yellow(`
1
+ import i from"os";import l from"path";import{existsSync as m,readFileSync as S,readdirSync as h,createWriteStream as g,mkdirSync as x,rmSync as I,unlinkSync as Z}from"fs";import{execFileSync as b}from"child_process";import{createInterface as v}from"readline";import a from"chalk";var A=process.env.ZIBBY_STUDIO_CDN||"https://dl.zibby.app",n=l.join(i.homedir(),".zibby","studio");function w(){let t=i.platform(),o=i.arch();if(t==="darwin"&&o==="arm64")return{archive:"Zibby Studio-mac-arm64.zip",label:"macOS (Apple Silicon)"};if(t==="darwin")return{archive:"Zibby Studio-mac-x64.zip",label:"macOS (Intel)"};if(t==="win32"&&o==="arm64")return{archive:"Zibby Studio-win-arm64.zip",label:"Windows (ARM)"};if(t==="win32")return{archive:"Zibby Studio-win-x64.zip",label:"Windows (x64)"};if(t==="linux"&&o==="arm64")return{archive:"Zibby Studio-arm64.AppImage",label:"Linux (ARM64)"};if(t==="linux")return{archive:"Zibby Studio-1.0.0.AppImage",label:"Linux (x64)"};throw new Error(`Unsupported platform: ${t} ${o}`)}function $(){let{archive:t}=w();return`${A}/download/latest/${encodeURIComponent(t)}`}function z(t){let o=v({input:process.stdin,output:process.stdout});return new Promise(e=>{o.question(t,u=>{o.close(),e(u.trim().toLowerCase())})})}async function C(){let{label:t}=w();console.log(""),console.log(a.cyan(" Zibby Studio is not installed.")),console.log(a.gray(` Platform: ${t}`)),console.log("");let o=await z(a.white(" Download and install Zibby Studio? (Y/n): "));return o&&o!=="y"&&o!=="yes"?(console.log(a.yellow(`
2
2
  Skipped.
3
- `)),!1):(await D(),!0)}async function D(){const t=$(),o=decodeURIComponent(a.basename(t));console.log(l.cyan(`
4
- \u{1F4E6} Downloading Zibby Studio...`));try{const e=await fetch(t);if(!e.ok)throw new Error(`Download failed: ${e.status} ${e.statusText}`);const u=parseInt(e.headers.get("content-length")||"0",10),c=a.join(i.tmpdir(),o);let f=0;const d=g(c);for await(const r of e.body)if(f+=r.length,d.write(r),u>0){const s=(f/u*100).toFixed(1),p=(f/1024/1024).toFixed(1),y=(u/1024/1024).toFixed(1);process.stdout.write(`\r \u{1F4E5} ${s}% (${p}MB / ${y}MB)`)}if(await new Promise((r,s)=>{d.on("finish",r),d.on("error",s),d.end()}),console.log(""),m(n)&&I(n,{recursive:!0,force:!0}),x(n,{recursive:!0}),console.log(l.cyan(" \u{1F4C2} Installing...")),c.endsWith(".zip"))if(i.platform()==="darwin"||i.platform()==="linux"){if(b("unzip",["-oq",c,"-d",n]),i.platform()==="darwin")try{b("xattr",["-cr",n])}catch{}}else{const r=(await import("adm-zip")).default;new r(c).extractAllTo(n,!0)}else if(c.endsWith(".AppImage")){const{copyFileSync:r,chmodSync:s}=await import("fs"),p=a.join(n,o);r(c,p),s(p,493)}try{Z(c)}catch{}return console.log(l.green(` \u2705 Zibby Studio installed!
5
- `)),!0}catch(e){throw console.log(l.red(`
3
+ `)),!1):(await D(),!0)}async function D(){let t=$(),o=decodeURIComponent(l.basename(t));console.log(a.cyan(`
4
+ \u{1F4E6} Downloading Zibby Studio...`));try{let e=await fetch(t);if(!e.ok)throw new Error(`Download failed: ${e.status} ${e.statusText}`);let u=parseInt(e.headers.get("content-length")||"0",10),c=l.join(i.tmpdir(),o),f=0,d=g(c);for await(let r of e.body)if(f+=r.length,d.write(r),u>0){let s=(f/u*100).toFixed(1),p=(f/1024/1024).toFixed(1),y=(u/1024/1024).toFixed(1);process.stdout.write(`\r \u{1F4E5} ${s}% (${p}MB / ${y}MB)`)}if(await new Promise((r,s)=>{d.on("finish",r),d.on("error",s),d.end()}),console.log(""),m(n)&&I(n,{recursive:!0,force:!0}),x(n,{recursive:!0}),console.log(a.cyan(" \u{1F4C2} Installing...")),c.endsWith(".zip"))if(i.platform()==="darwin"||i.platform()==="linux"){if(b("unzip",["-oq",c,"-d",n]),i.platform()==="darwin")try{b("xattr",["-cr",n])}catch{}}else{let r=(await import("adm-zip")).default;new r(c).extractAllTo(n,!0)}else if(c.endsWith(".AppImage")){let{copyFileSync:r,chmodSync:s}=await import("fs"),p=l.join(n,o);r(c,p),s(p,493)}try{Z(c)}catch{}return console.log(a.green(` \u2705 Zibby Studio installed!
5
+ `)),!0}catch(e){throw console.log(a.red(`
6
6
  \u274C Installation failed: ${e.message}
7
- `)),e}}function M(){const t=k();return!!(t&&m(t))}function k(){if(i.platform()==="darwin")return a.join(n,"Zibby Studio.app");if(i.platform()==="win32")return a.join(n,"Zibby Studio.exe");if(i.platform()==="linux"){if(!m(n))return null;const t=h(n).find(o=>o.endsWith(".AppImage"));return t?a.join(n,t):null}return null}function O(){const t=a.join(n,"version.txt");return m(t)?S(t,"utf-8").trim():"unknown"}export{k as getStudioAppPath,O as getStudioVersion,D as installStudio,M as isStudioInstalled,C as promptAndInstallStudio};
7
+ `)),e}}function M(){let t=k();return!!(t&&m(t))}function k(){if(i.platform()==="darwin")return l.join(n,"Zibby Studio.app");if(i.platform()==="win32")return l.join(n,"Zibby Studio.exe");if(i.platform()==="linux"){if(!m(n))return null;let t=h(n).find(o=>o.endsWith(".AppImage"));return t?l.join(n,t):null}return null}function O(){let t=l.join(n,"version.txt");return m(t)?S(t,"utf-8").trim():"unknown"}export{k as getStudioAppPath,O as getStudioVersion,D as installStudio,M as isStudioInstalled,C as promptAndInstallStudio};
@@ -1 +1 @@
1
- import{spawn as d,execFileSync as s}from"child_process";import c from"os";import a from"path";import{existsSync as l,mkdirSync as f,writeFileSync as m}from"fs";import{getStudioAppPath as S}from"./studio-installer.js";const p=a.join(c.homedir(),".zibby","studio-launch.json");function h(r){const o={};r.projectRoot&&(o.projectRoot=r.projectRoot),r.port&&(o.port=r.port),o.launchedAt=Date.now();const i=a.dirname(p);f(i,{recursive:!0}),m(p,JSON.stringify(o,null,2))}function w(r){if(c.platform()==="darwin"){try{s("xattr",["-cr",r])}catch{}try{s("spctl",["--add","--label","ZibbyStudio",r])}catch{}}}function u(r,o){return new Promise(i=>{const t=d("open",["-a",r,"--env",`ZIBBY_STUDIO_PROJECT_ROOT=${o.projectRoot}`],{stdio:["ignore","pipe","pipe"]});let e="";t.stderr?.on("data",n=>{e+=n.toString()}),t.on("close",n=>i({code:n,stderr:e})),t.on("error",n=>i({code:1,stderr:n.message}))})}async function j(r={}){const o=S();if(!o)throw new Error("Studio not installed");if(!l(o))throw new Error(`Studio app not found at ${o}`);h(r);const i=r.projectRoot||process.cwd();if(c.platform()==="darwin"){let t=await u(o,{projectRoot:i});if(t.code!==0&&t.stderr.includes("Launch failed")&&(w(o),t=await u(o,{projectRoot:i})),t.code!==0){const e=t.stderr.trim();e&&console.error(`[Studio Desktop] ${e}`),console.error(`Zibby Studio exited with code ${t.code}`)}}else{const t=d(o,[],{detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,ZIBBY_STUDIO_PROJECT_ROOT:i}});t.unref(),t.stderr?.on("data",e=>{const n=e.toString().trim();n&&console.error(`[Studio Desktop] ${n}`)}),t.on("error",e=>{console.error(`Failed to open Zibby Studio: ${e.message}`)})}}export{j as launchStudio};
1
+ import{spawn as m,execFileSync as p}from"child_process";import l from"os";import S from"path";import{existsSync as h,mkdirSync as b,writeFileSync as g}from"fs";import c from"os";import s from"path";import{existsSync as w,readFileSync as O,readdirSync as y,createWriteStream as j,mkdirSync as A,rmSync as D,unlinkSync as R}from"fs";import F from"chalk";var T=process.env.ZIBBY_STUDIO_CDN||"https://dl.zibby.app",a=s.join(c.homedir(),".zibby","studio");function d(){if(c.platform()==="darwin")return s.join(a,"Zibby Studio.app");if(c.platform()==="win32")return s.join(a,"Zibby Studio.exe");if(c.platform()==="linux"){if(!w(a))return null;let o=y(a).find(t=>t.endsWith(".AppImage"));return o?s.join(a,o):null}return null}var u=S.join(l.homedir(),".zibby","studio-launch.json");function x(o){let t={};o.projectRoot&&(t.projectRoot=o.projectRoot),o.port&&(t.port=o.port),t.launchedAt=Date.now();let n=S.dirname(u);b(n,{recursive:!0}),g(u,JSON.stringify(t,null,2))}function I(o){if(l.platform()==="darwin"){try{p("xattr",["-cr",o])}catch{}try{p("spctl",["--add","--label","ZibbyStudio",o])}catch{}}}function f(o,t){return new Promise(n=>{let e=m("open",["-a",o,"--env",`ZIBBY_STUDIO_PROJECT_ROOT=${t.projectRoot}`],{stdio:["ignore","pipe","pipe"]}),r="";e.stderr?.on("data",i=>{r+=i.toString()}),e.on("close",i=>n({code:i,stderr:r})),e.on("error",i=>n({code:1,stderr:i.message}))})}async function E(o={}){let t=d();if(!t)throw new Error("Studio not installed");if(!h(t))throw new Error(`Studio app not found at ${t}`);x(o);let n=o.projectRoot||process.cwd();if(l.platform()==="darwin"){let e=await f(t,{projectRoot:n});if(e.code!==0&&e.stderr.includes("Launch failed")&&(I(t),e=await f(t,{projectRoot:n})),e.code!==0){let r=e.stderr.trim();r&&console.error(`[Studio Desktop] ${r}`),console.error(`Zibby Studio exited with code ${e.code}`)}}else{let e=m(t,[],{detached:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,ZIBBY_STUDIO_PROJECT_ROOT:n}});e.unref(),e.stderr?.on("data",r=>{let i=r.toString().trim();i&&console.error(`[Studio Desktop] ${i}`)}),e.on("error",r=>{console.error(`Failed to open Zibby Studio: ${r.message}`)})}}export{E as launchStudio};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/cli",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "Zibby CLI - Test automation generator and runner",
5
5
  "type": "module",
6
6
  "bin": {