task-pipeliner 0.3.5 → 0.3.6

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/README.ko.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 조건 기반 실행과 아름다운 CLI 출력을 제공하는 강력한 워크플로우 오케스트레이션 도구
4
4
 
5
- **버전:** 0.3.5
5
+ **버전:** 0.3.6
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A powerful workflow orchestration tool with condition-based execution and beautiful CLI output
4
4
 
5
- **Version:** 0.3.5
5
+ **Version:** 0.3.6
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
package/dist/index.cjs CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var qt=Object.create;var Te=Object.defineProperty;var Gt=Object.getOwnPropertyDescriptor;var Zt=Object.getOwnPropertyNames;var Xt=Object.getPrototypeOf,Kt=Object.prototype.hasOwnProperty;var Qt=(r,e)=>()=>(r&&(e=r(r=0)),e);var eo=(r,e)=>{for(var t in e)Te(r,t,{get:e[t],enumerable:!0})},to=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Zt(e))!Kt.call(r,n)&&n!==t&&Te(r,n,{get:()=>e[n],enumerable:!(o=Gt(e,n))||o.enumerable});return r};var y=(r,e,t)=>(t=r!=null?qt(Xt(r)):{},to(e||!r||!r.__esModule?Te(t,"default",{value:r,enumerable:!0}):t,r));var tt={};eo(tt,{DAEMON_DIR:()=>Z,getDaemonErrorLogPath:()=>Ne,getDaemonPid:()=>Ie,getDaemonStartTime:()=>et,getDaemonStatus:()=>$,isDaemonRunning:()=>H,readDaemonErrorLog:()=>je,removeDaemonPid:()=>ae,saveDaemonPid:()=>ro,writeDaemonError:()=>Me});function oo(r){try{return process.kill(r,0),!0}catch{return!1}}async function Ie(){try{if(!(0,Y.existsSync)(_))return null;let r=await(0,x.readFile)(_,"utf-8"),e=parseInt(r.trim(),10);return isNaN(e)?(await(0,x.unlink)(_),null):oo(e)?e:(await(0,x.unlink)(_),null)}catch(r){if(r instanceof Error&&"code"in r&&r.code==="ENOENT")return null;throw r}}async function H(){return await Ie()!==null}async function ro(){await(0,x.mkdir)(Z,{recursive:!0}),await(0,x.writeFile)(_,process.pid.toString(),"utf-8");let r=new Date().toISOString();await(0,x.writeFile)(se,r,"utf-8")}async function Me(r){try{await(0,x.mkdir)(Z,{recursive:!0});let e=`${new Date().toISOString()} ${r.message}
2
+ "use strict";var xo=Object.create;var je=Object.defineProperty;var $o=Object.getOwnPropertyDescriptor;var Ro=Object.getOwnPropertyNames;var Eo=Object.getPrototypeOf,Po=Object.prototype.hasOwnProperty;var Co=(r,e)=>()=>(r&&(e=r(r=0)),e);var Do=(r,e)=>{for(var t in e)je(r,t,{get:e[t],enumerable:!0})},To=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Ro(e))!Po.call(r,n)&&n!==t&&je(r,n,{get:()=>e[n],enumerable:!(o=$o(e,n))||o.enumerable});return r};var b=(r,e,t)=>(t=r!=null?xo(Eo(r)):{},To(e||!r||!r.__esModule?je(t,"default",{value:r,enumerable:!0}):t,r));var lt={};Do(lt,{DAEMON_DIR:()=>ee,getDaemonErrorLogPath:()=>Oe,getDaemonPid:()=>Ae,getDaemonStartTime:()=>at,getDaemonStatus:()=>P,isDaemonRunning:()=>W,readDaemonErrorLog:()=>Fe,removeDaemonPid:()=>me,saveDaemonPid:()=>Mo,writeDaemonError:()=>Le});function Io(r){try{return process.kill(r,0),!0}catch{return!1}}async function Ae(){try{if(!(0,Z.existsSync)(V))return null;let r=await(0,E.readFile)(V,"utf-8"),e=parseInt(r.trim(),10);return isNaN(e)?(await(0,E.unlink)(V),null):Io(e)?e:(await(0,E.unlink)(V),null)}catch(r){if(r instanceof Error&&"code"in r&&r.code==="ENOENT")return null;throw r}}async function W(){return await Ae()!==null}async function Mo(){await(0,E.mkdir)(ee,{recursive:!0}),await(0,E.writeFile)(V,process.pid.toString(),"utf-8");let r=new Date().toISOString();await(0,E.writeFile)(pe,r,"utf-8")}async function Le(r){try{await(0,E.mkdir)(ee,{recursive:!0});let e=`${new Date().toISOString()} ${r.message}
3
3
  ${r.stack??""}
4
- `;await(0,x.writeFile)(fe,e,"utf-8")}catch{}}async function ae(){try{(0,Y.existsSync)(_)&&await(0,x.unlink)(_),(0,Y.existsSync)(se)&&await(0,x.unlink)(se)}catch{}}async function et(){try{if((0,Y.existsSync)(se)){let e=(await(0,x.readFile)(se,"utf-8")).trim();if(e)return e}if((0,Y.existsSync)(_)){let r=await(0,x.stat)(_);return new Date(r.mtime).toISOString()}return null}catch{return null}}function Ne(){return fe}async function je(){try{return(0,Y.existsSync)(fe)&&(await(0,x.readFile)(fe,"utf-8")).trim()||null}catch{return null}}async function $(){let r=await Ie(),e=r?await et():null;return{running:r!==null,pid:r,startTime:e}}var Y,x,Qe,ie,Z,_,se,fe,le=Qt(()=>{"use strict";Y=require("fs"),x=require("fs/promises"),Qe=require("os"),ie=require("path"),Z=(0,ie.join)((0,Qe.homedir)(),".pipeliner","daemon"),_=(0,ie.join)(Z,"scheduler.pid"),se=(0,ie.join)(Z,"scheduler.started");fe=(0,ie.join)(Z,"error.log")});var Vt=require("child_process"),O=require("fs"),F=require("fs/promises"),zt=require("os"),D=require("path"),Ut=require("util"),Ke=y(require("boxen"),1),p=y(require("chalk"),1),Yt=require("commander"),Jt=y(require("dayjs"),1);le();var q=require("path"),ut=y(require("chalk"),1),Se=y(require("log-update"),1);var rt=y(require("readline"),1),T=y(require("chalk"),1),Ae=y(require("inquirer"),1),ot=15,I=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,t){if(this.searchable)return this.promptWithSearch(e,t);let{choice:o}=await Ae.default.prompt([{type:"list",name:"choice",message:T.default.cyan(e),choices:t.map(s=>({name:s.label,value:s.id})),pageSize:ot}]),n=t.find(s=>s.id===o);if(!n)throw new Error(`Invalid choice: ${o}`);return n}async promptWithSearch(e,t){return new Promise(o=>{let n="",s=0,i=[...t],a=rt.createInterface({input:process.stdin,output:process.stdout,terminal:!1});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdout.write("\x1B[?1049h"),process.stdout.write("\x1B[?25l");let l=()=>{process.stdout.write("\x1B[H\x1B[2J"),console.log(T.default.cyan(`? ${e}`));let h=n?T.default.gray(` Filter: ${n}`)+T.default.gray(` (${i.length}/${t.length})`):T.default.gray(" Type to filter, \u2191\u2193 to navigate, Enter to select");console.log(h),console.log();let d=ot,w=0,b=i.length;if(i.length>d){let v=Math.floor(d/2);w=Math.max(0,s-v),b=Math.min(i.length,w+d),b===i.length&&(w=Math.max(0,b-d))}if(i.length===0)console.log(T.default.yellow(" No matches found"));else{w>0&&console.log(T.default.gray(` \u2191 ${w} more above`));for(let v=w;v<b;v++){let E=i[v];console.log(v===s?T.default.cyan(`\u276F ${E.label}`):T.default.white(` ${E.label}`))}b<i.length&&console.log(T.default.gray(` \u2193 ${i.length-b} more below`))}},c=()=>{let h=n.toLowerCase();i=h?t.filter(d=>d.label.toLowerCase().includes(h)):[...t],s>=i.length&&(s=Math.max(0,i.length-1))},f=h=>{let d=h.toString();if(d===""&&(g(),process.exit(0)),d==="\r"||d===`
5
- `){i.length>0&&(g(),o(i[s]));return}if(d==="\x1B"&&h.length===1){n&&(n="",c(),l());return}if(d==="\x1B[A"){i.length>0&&(s=s>0?s-1:i.length-1,l());return}if(d==="\x1B[B"){i.length>0&&(s=s<i.length-1?s+1:0,l());return}if(d==="\x7F"||d==="\b"){n.length>0&&(n=n.slice(0,-1),c(),l());return}d.length===1&&d>=" "&&d<="~"&&(n+=d,c(),l())},g=()=>{process.stdin.removeListener("data",f),process.stdin.isTTY&&process.stdin.setRawMode(!1),a.close(),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[?1049l")};l(),process.stdin.on("data",f)})}},me=class{async prompt(e,t){let{value:o}=await Ae.default.prompt([{type:"input",name:"value",message:T.default.cyan(e),default:t}]);return o}};var he=y(require("boxen"),1),X=y(require("chalk"),1);function Le(r,e,t,o={}){let{borderColor:n="cyan",isNested:s=!1}=o,i;e!==void 0&&(t?i=`line ${e} in ${t}`:i=`line ${e}`);let a=s?`\u2502 ${r}`:`> ${r}`;return(0,he.default)(a,{title:i,borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:n})}function K(r,e=!1,t){let o=r?"\u2713 Completed":"\u2717 Failed",n=r?X.default.green(o):X.default.red(o);if(t!==void 0){let s=Q(t);return`${n} ${X.default.gray(`(${s})`)}`}return n}function ce(r){return(0,he.default)(`\u2717 ${r}`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"red"})}function nt(r){return(0,he.default)(`> Starting parallel execution (${r} branches)`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"yellow"})}function st(r){let e=r?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return r?X.default.green(e):X.default.red(e)}function Oe(r,e=!1){return`${e?"| \u2502 ":"\u2502 "}${r}`}function Q(r){return`${(r/1e3).toFixed(3)}s`}var it=require("fs"),at=require("path"),ee=class{constructor(e){this.workspace=e}evaluate(e){return"var"in e||"has"in e?this.evaluateVarExists(e):"file"in e?this.evaluateFileExists(e):"choice"in e?this.evaluateChoice(e):"all"in e?this.evaluateAll(e):"any"in e?this.evaluateAny(e):"not"in e?this.evaluateNot(e):!1}evaluateVarExists(e){if(e.has)return this.workspace.hasVariable(e.has)||this.workspace.hasFact(e.has);if(!e.var)return!1;if(typeof e.var=="object"){for(let[o,n]of Object.entries(e.var)){let s=this.workspace.getVariable(o),i=this.workspace.getFact(o),a=s??(i!==void 0?i.toString():void 0);if(a===void 0||a!==n)return!1}return!0}let t=e.var;return this.workspace.hasVariable(t)||this.workspace.hasFact(t)}evaluateFileExists(e){try{let t=e.file.trim(),o=(0,at.resolve)(process.cwd(),t);return(0,it.existsSync)(o)}catch{return!1}}evaluateChoice(e){return this.workspace.hasChoice(e.choice)}evaluateAll(e){return e.all.every(t=>this.evaluate(t))}evaluateAny(e){return e.any.some(t=>this.evaluate(t))}evaluateNot(e){return!this.evaluate(e.not)}};var N=require("fs/promises"),lt=require("os"),J=require("path"),ct=y(require("dayjs"),1),te=(0,J.join)((0,lt.homedir)(),".pipeliner","workflow-history"),oe=class{constructor(){}async saveHistory(e){await(0,N.mkdir)(te,{recursive:!0});let t=(0,ct.default)().format("YYYY-MM-DD_HH-mm-ss"),o=Math.random().toString(36).slice(2,6),n=(0,J.join)(te,`workflow-${t}-${o}.json`);return await(0,N.writeFile)(n,JSON.stringify(e,null,2),{encoding:"utf8"}),n}async clearAllHistories(){await(0,N.rm)(te,{recursive:!0,force:!0})}async removeHistory(e){await(0,N.rm)((0,J.join)(te,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,N.readdir)(te)).map(o=>(0,J.basename)(o));return t.sort((o,n)=>{let s=l=>{let c=l.match(/workflow-(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-/);return c?c[1]:""},i=s(o),a=s(n);return i===a?n.localeCompare(o):a.localeCompare(i)}),t}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async getHistory(e){let t=await(0,N.readFile)((0,J.join)(te,e),{encoding:"utf8"});return JSON.parse(t)}};var ge=class{records=[];initialTimestamp=Date.now();recordStartTimestamp=Date.now();constructor(){this.records=[]}recordStart(){this.recordStartTimestamp=Date.now()}recordEnd(e,t,o,n){let s=this.getDuration();return this.records.push({step:e,context:t,output:o,duration:s,status:n}),s}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new oe,t={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(t)}getDuration(){return Date.now()-this.recordStartTimestamp}};var Fe=require("child_process");var we=class{async run(e,t,o,n,s=!1,i=!1,a,l,c,f,g){return s?this.runBuffered(e,c,f,g):this.runRealtime(e,o??e,i,a,l,c,f,g)}async runBuffered(e,t,o,n){return new Promise((s,i)=>{let a=this.spawnWithShell(e,t,n),l=[],c=[],f="",g="",h=null;o&&o>0&&(h=setTimeout(()=>{a.kill("SIGTERM");let d=`Command timed out after ${o} seconds`;c.push(d),s({success:!1,stdout:l,stderr:c})},o*1e3)),a.stdout?.on("data",d=>{let w=d.toString(),{lines:b,remaining:v}=this.processStreamBuffer(w,f);l.push(...b),f=v}),a.stderr?.on("data",d=>{let w=d.toString(),{lines:b,remaining:v}=this.processStreamBuffer(w,g);c.push(...b),g=v}),a.on("close",d=>{h&&clearTimeout(h),f.trim()&&l.push(f),g.trim()&&c.push(g),s({success:d===0,stdout:l,stderr:c})}),a.on("error",d=>{h&&clearTimeout(h);let w=`Error: ${d.message}`;s({success:!1,stdout:l,stderr:[...c,w]})})})}async runRealtime(e,t,o,n,s,i,a,l){let f=Le(t,n,s,{borderColor:o?"green":"cyan"});console.log(f);let g=Date.now();return new Promise(h=>{let d=this.spawnWithShell(e,i,l),w="",b="",v=null;a&&a>0&&(v=setTimeout(()=>{d.kill("SIGTERM");let E=`Command timed out after ${a} seconds`,M=ce(E);console.error(M);let B=Date.now()-g,W=K(!1,!1,B);console.log(W),h(!1)},a*1e3)),d.stdout?.on("data",E=>{let M=E.toString(),{lines:B,remaining:W}=this.processStreamBuffer(M,w);B.forEach(De=>process.stdout.write(`\u2502 ${De}
6
- `)),w=W}),d.stderr?.on("data",E=>{let M=E.toString(),{lines:B,remaining:W}=this.processStreamBuffer(M,b);B.forEach(De=>process.stderr.write(`\u2502 ${De}
7
- `)),b=W}),d.on("close",E=>{v&&clearTimeout(v),w.trim()&&process.stdout.write(`\u2502 ${w}
8
- `),b.trim()&&process.stderr.write(`\u2502 ${b}
9
- `);let M=E===0,B=Date.now()-g,W=K(M,!1,B);console.log(W),h(M)}),d.on("error",E=>{v&&clearTimeout(v);let M=ce(`Error: ${E.message}`);console.error(M),h(!1)})})}createSpawnOptions(e){let t={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(t.cwd=e),t}spawnWithShell(e,t,o){if(o&&o.length>0){let n=o[0],s=[...o.slice(1),e],i={stdio:["inherit","pipe","pipe"]};return t&&(i.cwd=t),(0,Fe.spawn)(n,s,i)}else{let n=process.env.SHELL??(process.platform==="win32"?"cmd.exe":"/bin/sh"),s=process.platform==="win32"?"/c":"-c",i={stdio:["inherit","pipe","pipe"]};return t&&(i.cwd=t),(0,Fe.spawn)(n,[s,e],i)}}processStreamBuffer(e,t){let o=t+e,n=[],s=o;for(;s.includes(`
10
- `);){let i=s.indexOf(`
11
- `),a=s.substring(0,i);s=s.substring(i+1),n.push(a)}return{lines:n,remaining:s}}formatNestedOutput(e,t){t?e.split(`
12
- `).forEach(o=>{o.trim()&&console.log(`| ${o}`)}):console.log(e)}displayBufferedOutput(e,t,o=!1,n,s){let i=Le(t,n,s,{borderColor:"cyan",isNested:o});this.formatNestedOutput(i,o),e.stdout.forEach(l=>{let c=Oe(l,o);process.stdout.write(`${c}
13
- `)}),e.stderr.forEach(l=>{let c=Oe(l,o);process.stderr.write(`${c}
14
- `)});let a=K(e.success,o);console.log(a)}};function no(r,e,t){if(e.hasVariable(r))return e.getVariable(r)??t;if(e.hasFact(r)){let o=e.getFact(r);return typeof o=="string"?o:String(o)}return e.hasChoice(r)?e.getChoice(r)??t:t}function ye(r,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return r.replace(t,(o,n)=>no(n,e,o))}var be=class r{state;constructor(){this.state={facts:new Map,choices:new Map,variables:new Map,stepResults:new Map,lastStepIndex:-1}}hasFact(e){return this.state.facts.has(e)}getFact(e){return this.state.facts.get(e)}setFact(e,t){this.state.facts.set(e,t)}getFactStatus(e){if(!this.hasFact(e))return"pending";let t=this.getFact(e);return t===!1||t==="failed"?"failed":"ready"}getAllFacts(){return new Map(this.state.facts)}hasChoice(e){return this.state.choices.has(e)}getChoice(e){return this.state.choices.get(e)}setChoice(e,t){this.state.choices.set(e,t)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,t){this.state.variables.set(e,t)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,t,o){this.state.stepResults.set(e,{success:t,exitCode:o}),this.state.lastStepIndex=e}getStepResult(e){return this.state.stepResults.get(e)}getLastStepResult(){if(this.state.lastStepIndex!==-1)return this.state.stepResults.get(this.state.lastStepIndex)}clone(){let e=new r;return e.state.facts=new Map(this.state.facts),e.state.choices=new Map(this.state.choices),e.state.variables=new Map(this.state.variables),e.state.stepResults=new Map(this.state.stepResults),e.state.lastStepIndex=this.state.lastStepIndex,e}};var re=class r{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new be,this.taskRunner=new we,this.choicePrompt=new I,this.textPrompt=new me}resolveBaseDir(e){if(e.baseDir)if((0,q.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,q.dirname)(e._filePath);this.baseDir=(0,q.resolve)(t,e.baseDir)}else this.baseDir=(0,q.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let o={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(o.lineNumber=t._lineNumbers.get(e)),t._fileName&&(o.fileName=t._fileName),o}evaluateStepCondition(e){return e.when?new ee(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/r.PARALLEL_STEP_INDEX_MULTIPLIER)}isRunStep(e){return"run"in e}async execute(e,t){if(t?.profileVars&&Object.keys(t.profileVars).length>0)for(let[a,l]of Object.entries(t.profileVars))this.workspace.setVariable(a,l);this.resolveBaseDir(e),this.globalShell=e.shell;let o=new ge,n=Date.now();for(let a=0;a<e.steps.length;a++){let l=e.steps[a],c=this.createStepContext(a,e),f=!!l.when;if(this.evaluateStepCondition(l)){o.recordStart();try{let g=await this.executeStep(l,c,!1,f);this.handleStepResult(l,c,a,g,o)}catch(g){throw this.handleStepError(l,c,a,g,o),g}}}let s=Date.now()-n,i=Q(s);console.log(ut.default.cyan(`
15
- Total execution time: ${i}`)),await o.save(),o.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,o,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(o);return c?c.success:!0})():this.isStepSuccessful(n,e),a=i?"success":"failure",l=s.recordEnd(e,t,n,a);if(!this.isRunStep(e)){let c=K(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${o}${c} completed, but workflow stopped due to continue: false`:`Step ${o}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${c} failed`)}}}handleStepError(e,t,o,n,s){this.workspace.setStepResult(o,!1);let i=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[i]};s.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,o,n);return o&&typeof s=="object"&&"stdout"in s,s}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await this.executeParallelStep(e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeSingleRun(e,t,o=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run.trim(),this.workspace),a=e.shell??this.globalShell,l=e.retry??0,c=l==="Infinity"||l===1/0,f=typeof l=="number"?l:0,g=e.timeout,h=!1,d=0;for(;c||d<=f;){let w=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,g,a),b=typeof w=="boolean"?w:w.success;if(h=w,b||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise(E=>setTimeout(E,v))}}return h}async executeRunStep(e,t,o=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),i=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return s;let a={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await this.executeRunChain(a,t,o,n)}async executeRunChain(e,t,o,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,o,n)}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.stepIndex,!0);return}}let s=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!s?.id)throw new Error(`Invalid choice result: ${JSON.stringify(s)}`);let i=o??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=ye(e.prompt.message,this.workspace),s=e.prompt.default?ye(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(o,i),this.workspace.setFact(o,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((o,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*r.PARALLEL_STEP_INDEX_MULTIPLIER+n,branchIndex:n,lineNumber:t.lineNumber,fileName:t.fileName}))}getBranchDisplayName(e,t){return"run"in e?e.run:"choose"in e?`Choose: ${e.choose.message}`:"prompt"in e?`Prompt: ${e.prompt.message}`:"fail"in e?`Fail: ${e.fail.message}`:`Branch ${t+1}`}async executeParallelBranches(e,t){let o=[],n=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let f=e[c],g=t[c];if(f.when&&!new ee(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);o.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(o,n[s])},100),a=o.map(async c=>{let{index:f}=c,g=e[f],h=t[f];c.status="running";try{let d=await this.executeStep(g,h,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:h}}catch(d){h.workspace.setStepResult(h.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(o,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,o=!1){let n=e.map(s=>{let i=s.index+1,a="",l="";switch(s.status){case"pending":a="\u25CB",l=`Branch ${i}: ${s.name} - Pending`;break;case"running":a=t,l=`Branch ${i}: ${s.name} - Running...`;break;case"success":a="\u2713",l=`Branch ${i}: ${s.name} - Completed`;break;case"failed":a="\u2717",l=`Branch ${i}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${a} ${l}`});o?(0,Se.default)(n.join(`
16
- `)):(0,Se.default)(n.join(`
17
- `))}displayParallelResults(e,t,o){let n=!0,s=!1;console.log("");for(let a of e){if(!a)continue;s=!0;let{index:l,result:c,error:f,context:g}=a;if(f){n=!1;let h=`Branch ${l+1} failed: ${f instanceof Error?f.message:String(f)}`,d=ce(h);console.error(d)}else if(c&&typeof c=="object"&&"stdout"in c){let h=c;if(n=n&&h.success,h.stdout.length>0||h.stderr.length>0||!h.success){let d=t[l],w=this.getBranchDisplayName(d,l);this.taskRunner.displayBufferedOutput(h,w,!1,g.lineNumber,g.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let i=st(n);return console.log(i),n}mergeParallelResults(e){for(let t of e){let o=t.workspace.getAllFacts(),n=t.workspace.getAllVariables();for(let[s,i]of o)this.workspace.setFact(s,i);for(let[s,i]of n)this.workspace.setVariable(s,i)}}countExecutableBranches(e,t){let o=0;for(let n=0;n<e.length;n++){let s=e[n],i=t[n];s.when&&!new ee(i.workspace).evaluate(s.when)||o++}return o}async executeParallelStep(e,t){let o=this.createParallelContexts(e,t),n=this.countExecutableBranches(e.parallel,o),s=nt(n);console.log(s);let i=await this.executeParallelBranches(e.parallel,o),a=this.displayParallelResults(i,e.parallel,t);if(this.workspace.setStepResult(t.stepIndex,a),!a){let l=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${l} failed: one or more branches failed`)}this.mergeParallelResults(o)}async executeFailStep(e,t){let o=new Error(e.fail.message);throw o.stack=void 0,o}};var ht=require("yaml"),He=require("zod");var u=require("zod"),so=u.z.object({file:u.z.string()}),io=u.z.object({var:u.z.union([u.z.string(),u.z.record(u.z.string(),u.z.string())]).optional(),has:u.z.string().optional()}),ao=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),lo=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),co=u.z.object({choice:u.z.string()}),uo=u.z.union([so,co,io,ao,lo]),A=u.z.lazy(()=>u.z.union([uo,u.z.object({all:u.z.array(A)}),u.z.object({any:u.z.array(A)}),u.z.object({not:A})])),pt=u.z.lazy(()=>u.z.object({run:u.z.string(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),onError:pt.optional()})),dt=u.z.object({run:u.z.string(),when:A.optional(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),continue:u.z.boolean().optional(),onError:pt.optional()}),po=u.z.object({choose:u.z.object({message:u.z.string(),options:u.z.array(u.z.object({id:u.z.string(),label:u.z.string()})),as:u.z.string().optional()}),when:A.optional()}),fo=u.z.object({prompt:u.z.object({message:u.z.string(),as:u.z.string(),default:u.z.string().optional(),validate:u.z.string().optional()}),when:A.optional()});function ft(r){if(!r||typeof r!="object")return{found:!1};let e=r;if("choose"in e)return{found:!0,type:"choose"};if("prompt"in e)return{found:!0,type:"prompt"};if("parallel"in e&&Array.isArray(e.parallel))for(let t of e.parallel){let o=ft(t);if(o.found)return o}return{found:!1}}var mt=u.z.lazy(()=>u.z.union([dt,u.z.object({parallel:u.z.array(u.z.lazy(()=>mt)),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})]).superRefine((r,e)=>{let t=ft(r);t.found&&e.addIssue({code:u.z.ZodIssueCode.custom,message:`'${t.type}' step is not allowed inside 'parallel' block (user input cannot run in parallel)`})})),mo=u.z.lazy(()=>u.z.union([dt,po,fo,u.z.object({parallel:u.z.array(mt),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})])),ho=u.z.object({name:u.z.string().min(1,"Profile name must be non-empty"),var:u.z.record(u.z.string(),u.z.union([u.z.string(),u.z.number(),u.z.boolean()]).transform(String))}),go=u.z.object({name:u.z.string().optional(),baseDir:u.z.string().optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),profiles:u.z.array(ho).optional(),steps:u.z.array(mo).min(1,"Workflow must have at least one step")});function Be(r){return go.parse(r)}function gt(r,e){let t=r.path;if(r.code==="custom"){let n=We(t);return` - ${r.message}${n}`}if(r.message==="Invalid input"){let n=We(t),s=wo(t,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let o=We(t);return` - ${r.message}${o}`}function We(r){if(r.length===0)return"";let e=[];for(let t=0;t<r.length;t++){let o=r[t],n=r[t+1];o==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),t++):o==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),t++):typeof o=="string"&&o!=="steps"&&o!=="parallel"&&e.push(o)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function k(r,e,t){let o=t?`
4
+ `;await(0,E.writeFile)(be,e,"utf-8")}catch{}}async function me(){try{(0,Z.existsSync)(V)&&await(0,E.unlink)(V),(0,Z.existsSync)(pe)&&await(0,E.unlink)(pe)}catch{}}async function at(){try{if((0,Z.existsSync)(pe)){let e=(await(0,E.readFile)(pe,"utf-8")).trim();if(e)return e}if((0,Z.existsSync)(V)){let r=await(0,E.stat)(V);return new Date(r.mtime).toISOString()}return null}catch{return null}}function Oe(){return be}async function Fe(){try{return(0,Z.existsSync)(be)&&(await(0,E.readFile)(be,"utf-8")).trim()||null}catch{return null}}async function P(){let r=await Ae(),e=r?await at():null;return{running:r!==null,pid:r,startTime:e}}var Z,E,it,de,ee,V,pe,be,te=Co(()=>{"use strict";Z=require("fs"),E=require("fs/promises"),it=require("os"),de=require("path"),ee=(0,de.join)((0,it.homedir)(),".pipeliner","daemon"),V=(0,de.join)(ee,"scheduler.pid"),pe=(0,de.join)(ee,"scheduler.started");be=(0,de.join)(ee,"error.log")});var wo=require("child_process"),Y=require("fs"),J=require("fs/promises"),yo=require("os"),_=require("path"),bo=require("util"),g=b(require("chalk"),1),So=require("commander");te();var Q=require("path"),vt=b(require("chalk"),1);var ut=b(require("readline"),1),j=b(require("chalk"),1),Be=b(require("inquirer"),1),ct=15,I=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,t){if(this.searchable)return this.promptWithSearch(e,t);let{choice:o}=await Be.default.prompt([{type:"list",name:"choice",message:j.default.cyan(e),choices:t.map(i=>({name:i.label,value:i.id})),pageSize:ct}]),n=t.find(i=>i.id===o);if(!n)throw new Error(`Invalid choice: ${o}`);return n}async promptWithSearch(e,t){return new Promise(o=>{let n="",i=0,s=[...t],a=ut.createInterface({input:process.stdin,output:process.stdout,terminal:!1});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdout.write("\x1B[?1049h"),process.stdout.write("\x1B[?25l");let l=()=>{process.stdout.write("\x1B[H\x1B[2J"),console.log(j.default.cyan(`? ${e}`));let f=n?j.default.gray(` Filter: ${n}`)+j.default.gray(` (${s.length}/${t.length})`):j.default.gray(" Type to filter, \u2191\u2193 to navigate, Enter to select");console.log(f),console.log();let p=ct,h=0,w=s.length;if(s.length>p){let v=Math.floor(p/2);h=Math.max(0,i-v),w=Math.min(s.length,h+p),w===s.length&&(h=Math.max(0,w-p))}if(s.length===0)console.log(j.default.yellow(" No matches found"));else{h>0&&console.log(j.default.gray(` \u2191 ${h} more above`));for(let v=h;v<w;v++){let C=s[v];console.log(v===i?j.default.cyan(`\u276F ${C.label}`):j.default.white(` ${C.label}`))}w<s.length&&console.log(j.default.gray(` \u2193 ${s.length-w} more below`))}},c=()=>{let f=n.toLowerCase();s=f?t.filter(p=>p.label.toLowerCase().includes(f)):[...t],i>=s.length&&(i=Math.max(0,s.length-1))},d=f=>{let p=f.toString();if(p===""&&(m(),process.exit(0)),p==="\r"||p===`
5
+ `){s.length>0&&(m(),o(s[i]));return}if(p==="\x1B"&&f.length===1){n&&(n="",c(),l());return}if(p==="\x1B[A"){s.length>0&&(i=i>0?i-1:s.length-1,l());return}if(p==="\x1B[B"){s.length>0&&(i=i<s.length-1?i+1:0,l());return}if(p==="\x7F"||p==="\b"){n.length>0&&(n=n.slice(0,-1),c(),l());return}p.length===1&&p>=" "&&p<="~"&&(n+=p,c(),l())},m=()=>{process.stdin.removeListener("data",d),process.stdin.isTTY&&process.stdin.setRawMode(!1),a.close(),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[?1049l")};l(),process.stdin.on("data",d)})}},Se=class{async prompt(e,t){let{value:o}=await Be.default.prompt([{type:"input",name:"value",message:j.default.cyan(e),default:t}]);return o}};var ke=b(require("boxen"),1),oe=b(require("chalk"),1);function Ve(r,e,t,o={}){let{borderColor:n="cyan",isNested:i=!1}=o,s;e!==void 0&&(t?s=`line ${e} in ${t}`:s=`line ${e}`);let a=i?`\u2502 ${r}`:`> ${r}`;return(0,ke.default)(a,{title:s,borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:n})}function re(r,e=!1,t){let o=r?"\u2713 Completed":"\u2717 Failed",n=r?oe.default.green(o):oe.default.red(o);if(t!==void 0){let i=ne(t);return`${n} ${oe.default.gray(`(${i})`)}`}return n}function fe(r){return(0,ke.default)(`\u2717 ${r}`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"red"})}function pt(r){return(0,ke.default)(`> Starting parallel execution (${r} branches)`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"yellow"})}function dt(r){let e=r?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return r?oe.default.green(e):oe.default.red(e)}function We(r,e=!1){return`${e?"| \u2502 ":"\u2502 "}${r}`}function ne(r){return`${(r/1e3).toFixed(3)}s`}var mt=require("fs"),ft=require("path"),X=class{constructor(e){this.workspace=e}evaluate(e){return"var"in e||"has"in e?this.evaluateVarExists(e):"file"in e?this.evaluateFileExists(e):"choice"in e?this.evaluateChoice(e):"all"in e?this.evaluateAll(e):"any"in e?this.evaluateAny(e):"not"in e?this.evaluateNot(e):!1}evaluateVarExists(e){if(e.has)return this.workspace.hasVariable(e.has)||this.workspace.hasFact(e.has);if(!e.var)return!1;if(typeof e.var=="object"){for(let[o,n]of Object.entries(e.var)){let i=this.workspace.getVariable(o),s=this.workspace.getFact(o),a=i??(s!==void 0?s.toString():void 0);if(a===void 0||a!==n)return!1}return!0}let t=e.var;return this.workspace.hasVariable(t)||this.workspace.hasFact(t)}evaluateFileExists(e){try{let t=e.file.trim(),o=(0,ft.resolve)(process.cwd(),t);return(0,mt.existsSync)(o)}catch{return!1}}evaluateChoice(e){return this.workspace.hasChoice(e.choice)}evaluateAll(e){return e.all.every(t=>this.evaluate(t))}evaluateAny(e){return e.any.some(t=>this.evaluate(t))}evaluateNot(e){return!this.evaluate(e.not)}};var He=b(require("log-update"),1);var _e=1e3;function No(r,e,t){return e.parallel.map((o,n)=>({workspace:r.workspace.clone(),stepIndex:t.stepIndex*_e+n,branchIndex:n,lineNumber:t.lineNumber,fileName:t.fileName}))}function ht(r,e){return"run"in r?r.run:"choose"in r?`Choose: ${r.choose.message}`:"prompt"in r?`Prompt: ${r.prompt.message}`:"fail"in r?`Fail: ${r.fail.message}`:`Branch ${e+1}`}function jo(r,e){let t=0;for(let o=0;o<r.length;o++){let n=r[o],i=e[o];n.when&&!new X(i.workspace).evaluate(n.when)||t++}return t}function ve(r,e,t=!1){let o=r.map(n=>{let i=n.index+1,s="",a="";switch(n.status){case"pending":s="\u25CB",a=`Branch ${i}: ${n.name} - Pending`;break;case"running":s=e,a=`Branch ${i}: ${n.name} - Running...`;break;case"success":s="\u2713",a=`Branch ${i}: ${n.name} - Completed`;break;case"failed":s="\u2717",a=`Branch ${i}: ${n.name} - Failed${n.error?`: ${n.error}`:""}`;break}return`${s} ${a}`});(0,He.default)(o.join(`
6
+ `))}async function Ao(r,e,t,o){let n=[],i=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let d=0;d<t.length;d++){let m=t[d],f=o[d];if(m.when&&!new X(f.workspace).evaluate(m.when))continue;let p=e(m,d);n.push({index:d,name:p,status:"pending"})}let a=setInterval(()=>{s=(s+1)%i.length,ve(n,i[s])},100),l=n.map(async d=>{let{index:m}=d,f=t[m],p=o[m];d.status="running";try{let h=await r.executeStep(f,p,!0);return d.status="success",ve(n,i[s]),{index:m,result:h,context:p}}catch(h){p.workspace.setStepResult(p.stepIndex,!1);let w=h instanceof Error?h.message:String(h);return d.status="failed",d.error=w,ve(n,i[s]),{index:m,error:h,context:p}}}),c=await Promise.all(l);return clearInterval(a),ve(n,"",!0),He.default.done(),c}function Lo(r,e,t,o,n){let i=!0,s=!1;console.log("");for(let l of t){if(!l)continue;s=!0;let{index:c,result:d,error:m,context:f}=l;if(m){i=!1;let p=`Branch ${c+1} failed: ${m instanceof Error?m.message:String(m)}`,h=fe(p);console.error(h)}else if(d&&typeof d=="object"&&"stdout"in d){let p=d;if(i=i&&p.success,p.stdout.length>0||p.stderr.length>0||!p.success){let h=o[c],w=e(h,c);r.taskRunner.displayBufferedOutput(p,w,!1,f.lineNumber,f.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let a=dt(i);return console.log(a),i}function Oo(r,e){for(let t of e){let o=t.workspace.getAllFacts(),n=t.workspace.getAllVariables();for(let[i,s]of o)r.workspace.setFact(i,s);for(let[i,s]of n)r.workspace.setVariable(i,s)}}async function gt(r,e,t){let o=No(r,e,t),n=jo(e.parallel,o),i=pt(n);console.log(i);let s=await Ao(r,ht,e.parallel,o),a=Lo(r,ht,s,e.parallel,t);if(r.setStepResult(t.stepIndex,a),!a){let l=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${l} failed: one or more branches failed`)}Oo(r,o)}function Fo(r,e,t){if(e.hasVariable(r))return e.getVariable(r)??t;if(e.hasFact(r)){let o=e.getFact(r);return typeof o=="string"?o:String(o)}return e.hasChoice(r)?e.getChoice(r)??t:t}function se(r,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return r.replace(t,(o,n)=>Fo(n,e,o))}async function wt(r,e,t,o,n){let{workspace:i,taskRunner:s,baseDir:a,globalShell:l,calculateBaseStepIndex:c}=r,d=c(t),m=se(e.run.trim(),i),f=e.shell??l,p=e.retry??0,h=p==="Infinity"||p===1/0,w=typeof p=="number"?p:0,v=e.timeout,C=!1,R=0,O=e.run.trim()!==m?`${m}
7
+ (template: ${e.run})`:m;for(;h||R<=w;){let T=await s.run(m,d,O,t.branchIndex,o,n,t.lineNumber,t.fileName,a,v,f),G=typeof T=="boolean"?T:T.success;if(C=T,G||!h&&R>=w)break;if(R++,h||R<=w){let ko=Math.min(1e3*Math.pow(2,R-1),1e4);await new Promise(vo=>setTimeout(vo,ko))}}return C}async function yt(r,e,t,o,n){let i=await wt(r,{run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof i=="boolean"?i:i.success)||!e.onError?i:yt(r,e.onError,t,o,n)}async function bt(r,e,t,o=!1,n=!1){let{workspace:i}=r,s=await wt(r,{run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),a=typeof s=="boolean"?s:s.success;if(i.setStepResult(t.stepIndex,a),a||!e.onError)return s;let l={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await yt(r,l,t,o,n)}var L=require("fs/promises"),St=require("os"),K=require("path"),kt=b(require("dayjs"),1),ie=(0,K.join)((0,St.homedir)(),".pipeliner","workflow-history"),ae=class{constructor(){}async saveHistory(e){await(0,L.mkdir)(ie,{recursive:!0});let t=(0,kt.default)().format("YYYY-MM-DD_HH-mm-ss"),o=Math.random().toString(36).slice(2,6),n=(0,K.join)(ie,`workflow-${t}-${o}.json`);return await(0,L.writeFile)(n,JSON.stringify(e,null,2),{encoding:"utf8"}),n}async clearAllHistories(){await(0,L.rm)(ie,{recursive:!0,force:!0})}async removeHistory(e){await(0,L.rm)((0,K.join)(ie,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,L.readdir)(ie)).map(o=>(0,K.basename)(o));return t.sort((o,n)=>{let i=l=>{let c=l.match(/workflow-(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-/);return c?c[1]:""},s=i(o),a=i(n);return s===a?n.localeCompare(o):a.localeCompare(s)}),t}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async getHistory(e){let t=await(0,L.readFile)((0,K.join)(ie,e),{encoding:"utf8"});return JSON.parse(t)}};var xe=class{records=[];initialTimestamp=Date.now();recordStartTimestamp=Date.now();constructor(){this.records=[]}recordStart(){this.recordStartTimestamp=Date.now()}recordEnd(e,t,o,n,i){let s=this.getDuration();return this.records.push({step:e,context:t,output:o,duration:s,status:n,...i}),s}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new ae,t={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(t)}getDuration(){return Date.now()-this.recordStartTimestamp}};var ze=require("child_process");var $e=class{async run(e,t,o,n,i=!1,s=!1,a,l,c,d,m){return i?this.runBuffered(e,c,d,m):this.runRealtime(e,o??e,s,a,l,c,d,m)}async runBuffered(e,t,o,n){return new Promise((i,s)=>{let a=this.spawnWithShell(e,t,n),l=[],c=[],d="",m="",f=null;o&&o>0&&(f=setTimeout(()=>{a.kill("SIGTERM");let p=`Command timed out after ${o} seconds`;c.push(p),i({success:!1,stdout:l,stderr:c})},o*1e3)),a.stdout?.on("data",p=>{let h=p.toString(),{lines:w,remaining:v}=this.processStreamBuffer(h,d);l.push(...w),d=v}),a.stderr?.on("data",p=>{let h=p.toString(),{lines:w,remaining:v}=this.processStreamBuffer(h,m);c.push(...w),m=v}),a.on("close",p=>{f&&clearTimeout(f),d.trim()&&l.push(d),m.trim()&&c.push(m),i({success:p===0,stdout:l,stderr:c})}),a.on("error",p=>{f&&clearTimeout(f);let h=`Error: ${p.message}`;i({success:!1,stdout:l,stderr:[...c,h]})})})}async runRealtime(e,t,o,n,i,s,a,l){let d=Ve(t,n,i,{borderColor:o?"green":"cyan"});console.log(d);let m=Date.now();return new Promise(f=>{let p=this.spawnWithShell(e,s,l),h="",w="",v=null;a&&a>0&&(v=setTimeout(()=>{p.kill("SIGTERM");let C=`Command timed out after ${a} seconds`,R=fe(C);console.error(R);let O=Date.now()-m,T=re(!1,!1,O);console.log(T),f(!1)},a*1e3)),p.stdout?.on("data",C=>{let R=C.toString(),{lines:O,remaining:T}=this.processStreamBuffer(R,h);O.forEach(G=>process.stdout.write(`\u2502 ${G}
8
+ `)),h=T}),p.stderr?.on("data",C=>{let R=C.toString(),{lines:O,remaining:T}=this.processStreamBuffer(R,w);O.forEach(G=>process.stderr.write(`\u2502 ${G}
9
+ `)),w=T}),p.on("close",C=>{v&&clearTimeout(v),h.trim()&&process.stdout.write(`\u2502 ${h}
10
+ `),w.trim()&&process.stderr.write(`\u2502 ${w}
11
+ `);let R=C===0,O=Date.now()-m,T=re(R,!1,O);console.log(T),f(R)}),p.on("error",C=>{v&&clearTimeout(v);let R=fe(`Error: ${C.message}`);console.error(R),f(!1)})})}createSpawnOptions(e){let t={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(t.cwd=e),t}spawnWithShell(e,t,o){if(o&&o.length>0){let n=o[0],i=[...o.slice(1),e],s={stdio:["inherit","pipe","pipe"]};return t&&(s.cwd=t),(0,ze.spawn)(n,i,s)}else{let n=process.env.SHELL??(process.platform==="win32"?"cmd.exe":"/bin/sh"),i=process.platform==="win32"?"/c":"-c",s={stdio:["inherit","pipe","pipe"]};return t&&(s.cwd=t),(0,ze.spawn)(n,[i,e],s)}}processStreamBuffer(e,t){let o=t+e,n=[],i=o;for(;i.includes(`
12
+ `);){let s=i.indexOf(`
13
+ `),a=i.substring(0,s);i=i.substring(s+1),n.push(a)}return{lines:n,remaining:i}}formatNestedOutput(e,t){t?e.split(`
14
+ `).forEach(o=>{o.trim()&&console.log(`| ${o}`)}):console.log(e)}displayBufferedOutput(e,t,o=!1,n,i){let s=Ve(t,n,i,{borderColor:"cyan",isNested:o});this.formatNestedOutput(s,o),e.stdout.forEach(l=>{let c=We(l,o);process.stdout.write(`${c}
15
+ `)}),e.stderr.forEach(l=>{let c=We(l,o);process.stderr.write(`${c}
16
+ `)});let a=re(e.success,o);console.log(a)}};var Re=class r{state;constructor(){this.state={facts:new Map,choices:new Map,variables:new Map,stepResults:new Map,lastStepIndex:-1}}hasFact(e){return this.state.facts.has(e)}getFact(e){return this.state.facts.get(e)}setFact(e,t){this.state.facts.set(e,t)}getFactStatus(e){if(!this.hasFact(e))return"pending";let t=this.getFact(e);return t===!1||t==="failed"?"failed":"ready"}getAllFacts(){return new Map(this.state.facts)}hasChoice(e){return this.state.choices.has(e)}getChoice(e){return this.state.choices.get(e)}setChoice(e,t){this.state.choices.set(e,t)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,t){this.state.variables.set(e,t)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,t,o){this.state.stepResults.set(e,{success:t,exitCode:o}),this.state.lastStepIndex=e}getStepResult(e){return this.state.stepResults.get(e)}getLastStepResult(){if(this.state.lastStepIndex!==-1)return this.state.stepResults.get(this.state.lastStepIndex)}clone(){let e=new r;return e.state.facts=new Map(this.state.facts),e.state.choices=new Map(this.state.choices),e.state.variables=new Map(this.state.variables),e.state.stepResults=new Map(this.state.stepResults),e.state.lastStepIndex=this.state.lastStepIndex,e}};var le=class{workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new Re,this.taskRunner=new $e,this.choicePrompt=new I,this.textPrompt=new Se}resolveBaseDir(e){if(e.baseDir)if((0,Q.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,Q.dirname)(e._filePath);this.baseDir=(0,Q.resolve)(t,e.baseDir)}else this.baseDir=(0,Q.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let o={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(o.lineNumber=t._lineNumbers.get(e)),t._fileName&&(o.fileName=t._fileName),o}evaluateStepCondition(e){return e.when?new X(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/_e)}isRunStep(e){return"run"in e}getRecordResolved(e){if("run"in e)return{resolvedCommand:se(e.run.trim(),this.workspace)};if("choose"in e){let t=e.choose.as&&this.workspace.hasVariable(e.choose.as)?this.workspace.getVariable(e.choose.as):e.choose.options.find(o=>this.workspace.getChoice(o.id))?.id;return t!==void 0?{choiceValue:t}:void 0}if("prompt"in e){let t=this.workspace.getFact(e.prompt.as);return t!==void 0?{promptValue:t}:void 0}}async execute(e,t){if(t?.profileVars&&Object.keys(t.profileVars).length>0)for(let[a,l]of Object.entries(t.profileVars))this.workspace.setVariable(a,l);this.resolveBaseDir(e),this.globalShell=e.shell;let o=new xe,n=Date.now();for(let a=0;a<e.steps.length;a++){let l=e.steps[a],c=this.createStepContext(a,e),d=!!l.when;if(this.evaluateStepCondition(l)){o.recordStart();try{let m=await this.executeStep(l,c,!1,d);this.handleStepResult(l,c,a,m,o)}catch(m){throw this.handleStepError(l,c,a,m,o),m}}}let i=Date.now()-n,s=ne(i);console.log(vt.default.cyan(`
17
+ Total execution time: ${s}`)),await o.save(),o.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,o,n,i){let s=this.isRunStep(e)?(()=>{let d=this.workspace.getStepResult(o);return d?d.success:!0})():this.isStepSuccessful(n,e),a=s?"success":"failure",l=this.getRecordResolved(e),c=i.recordEnd(e,t,n,a,l);if(!this.isRunStep(e)){let d=re(s,!1,c);console.log(d)}if(this.isRunStep(e)){if(e.continue===!1){let d=t.lineNumber?` (line ${t.lineNumber})`:"",m=s?`Step ${o}${d} completed, but workflow stopped due to continue: false`:`Step ${o}${d} failed`;throw new Error(m)}if(!s&&e.continue!==!0){let d=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${d} failed`)}}}handleStepError(e,t,o,n,i){this.workspace.setStepResult(o,!1);let s=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[s]},l=this.getRecordResolved(e);i.recordEnd(e,t,a,"failure",l)}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let i=await bt({workspace:this.workspace,taskRunner:this.taskRunner,baseDir:this.baseDir,globalShell:this.globalShell,calculateBaseStepIndex:s=>this.calculateBaseStepIndex(s)},e,t,o,n);return o&&typeof i=="object"&&"stdout"in i,i}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await gt({workspace:this.workspace,taskRunner:this.taskRunner,executeStep:(i,s,a)=>this.executeStep(i,s,a,!!i.when),setStepResult:(i,s)=>this.workspace.setStepResult(i,s)},e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.stepIndex,!0);return}}let i=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!i?.id)throw new Error(`Invalid choice result: ${JSON.stringify(i)}`);let s=o??i.id;this.workspace.setChoice(i.id,i.id),this.workspace.setVariable(s,i.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=se(e.prompt.message,this.workspace),i=e.prompt.default?se(e.prompt.default,this.workspace):void 0,s=await this.textPrompt.prompt(n,i);this.workspace.setVariable(o,s),this.workspace.setFact(o,s),this.workspace.setStepResult(t.stepIndex,!0)}async executeFailStep(e,t){let o=new Error(e.fail.message);throw o.stack=void 0,o}};var Pt=require("yaml"),qe=require("zod");var u=require("zod"),Bo=u.z.object({file:u.z.string()}),Vo=u.z.object({var:u.z.union([u.z.string(),u.z.record(u.z.string(),u.z.string())]).optional(),has:u.z.string().optional()}),Wo=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),Ho=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),_o=u.z.object({choice:u.z.string()}),zo=u.z.union([Bo,_o,Vo,Wo,Ho]),F=u.z.lazy(()=>u.z.union([zo,u.z.object({all:u.z.array(F)}),u.z.object({any:u.z.array(F)}),u.z.object({not:F})])),xt=u.z.lazy(()=>u.z.object({run:u.z.string(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),onError:xt.optional()})),$t=u.z.object({run:u.z.string(),when:F.optional(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),continue:u.z.boolean().optional(),onError:xt.optional()}),Uo=u.z.object({choose:u.z.object({message:u.z.string(),options:u.z.array(u.z.object({id:u.z.string(),label:u.z.string()})),as:u.z.string().optional()}),when:F.optional()}),Yo=u.z.object({prompt:u.z.object({message:u.z.string(),as:u.z.string(),default:u.z.string().optional(),validate:u.z.string().optional()}),when:F.optional()});function Rt(r){if(!r||typeof r!="object")return{found:!1};let e=r;if("choose"in e)return{found:!0,type:"choose"};if("prompt"in e)return{found:!0,type:"prompt"};if("parallel"in e&&Array.isArray(e.parallel))for(let t of e.parallel){let o=Rt(t);if(o.found)return o}return{found:!1}}var Et=u.z.lazy(()=>u.z.union([$t,u.z.object({parallel:u.z.array(u.z.lazy(()=>Et)),when:F.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:F.optional()})]).superRefine((r,e)=>{let t=Rt(r);t.found&&e.addIssue({code:u.z.ZodIssueCode.custom,message:`'${t.type}' step is not allowed inside 'parallel' block (user input cannot run in parallel)`})})),Jo=u.z.lazy(()=>u.z.union([$t,Uo,Yo,u.z.object({parallel:u.z.array(Et),when:F.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:F.optional()})])),qo=u.z.object({name:u.z.string().min(1,"Profile name must be non-empty"),var:u.z.record(u.z.string(),u.z.union([u.z.string(),u.z.number(),u.z.boolean()]).transform(String))}),Go=u.z.object({name:u.z.string().optional(),baseDir:u.z.string().optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),profiles:u.z.array(qo).optional(),steps:u.z.array(Jo).min(1,"Workflow must have at least one step")});function Ue(r){return Go.parse(r)}function Ct(r,e){let t=r.path;if(r.code==="custom"){let n=Ye(t);return` - ${r.message}${n}`}if(r.message==="Invalid input"){let n=Ye(t),i=Zo(t,e);return i?` - ${i}${n}`:` - Invalid step type${n}`}let o=Ye(t);return` - ${r.message}${o}`}function Ye(r){if(r.length===0)return"";let e=[];for(let t=0;t<r.length;t++){let o=r[t],n=r[t+1];o==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),t++):o==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),t++):typeof o=="string"&&o!=="steps"&&o!=="parallel"&&e.push(o)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function $(r,e,t){let o=t?`
18
18
  Reason: ${t}`:"";throw new Error(`Invalid workflow structure:
19
- - ${e} (step ${r+1})${o}`)}function wt(r,e,t=!1,o=[]){let n=["run","choose","prompt","parallel","fail"],s=n.find(i=>i in r);if(!s){let i=Object.keys(r).filter(a=>a!=="when");k(e,`Unknown step type. Found keys: [${i.join(", ")}]. Valid types: ${n.join(", ")}`)}if(s==="run"){let i=r.run;if(typeof i!="string"&&k(e,"'run' must be a string command"),i===""&&k(e,"'run' command cannot be empty"),"shell"in r&&r.shell!==void 0){Array.isArray(r.shell)||k(e,"'shell' must be an array");let a=r.shell;a.length===0&&k(e,"'shell' cannot be empty","Shell configuration must have at least one element (program name)");for(let l=0;l<a.length;l++)typeof a[l]!="string"&&k(e,`'shell[${l}]' must be a string`)}}if(s==="choose"){if(t){let l=o.join(" \u2192 ");throw new Error(`Invalid workflow structure:
19
+ - ${e} (step ${r+1})${o}`)}function Dt(r,e,t=!1,o=[]){let n=["run","choose","prompt","parallel","fail"],i=n.find(s=>s in r);if(!i){let s=Object.keys(r).filter(a=>a!=="when");$(e,`Unknown step type. Found keys: [${s.join(", ")}]. Valid types: ${n.join(", ")}`)}if(i==="run"){let s=r.run;if(typeof s!="string"&&$(e,"'run' must be a string command"),s===""&&$(e,"'run' command cannot be empty"),"shell"in r&&r.shell!==void 0){Array.isArray(r.shell)||$(e,"'shell' must be an array");let a=r.shell;a.length===0&&$(e,"'shell' cannot be empty","Shell configuration must have at least one element (program name)");for(let l=0;l<a.length;l++)typeof a[l]!="string"&&$(e,`'shell[${l}]' must be a string`)}}if(i==="choose"){if(t){let l=o.join(" \u2192 ");throw new Error(`Invalid workflow structure:
20
20
  - 'choose' step is not allowed inside 'parallel' block (step ${e+1}, ${l})
21
- Reason: User input prompts cannot run in parallel`)}let i=r.choose;(!i||typeof i!="object")&&k(e,"'choose' must be an object with 'message' and 'options'");let a=i;(!a.message||typeof a.message!="string")&&k(e,"'choose.message' is required and must be a string"),Array.isArray(a.options)||k(e,"'choose.options' is required and must be an array"),a.options.length===0&&k(e,"'choose.options' cannot be empty","At least one option is required");for(let l=0;l<a.options.length;l++){let c=a.options[l];(!c||typeof c!="object")&&k(e,`'choose.options[${l}]' must be an object with 'id' and 'label'`),(!c.id||typeof c.id!="string")&&k(e,`'choose.options[${l}].id' is required and must be a string`),(!c.label||typeof c.label!="string")&&k(e,`'choose.options[${l}].label' is required and must be a string`)}}if(s==="prompt"){if(t){let l=o.join(" \u2192 ");throw new Error(`Invalid workflow structure:
21
+ Reason: User input prompts cannot run in parallel`)}let s=r.choose;(!s||typeof s!="object")&&$(e,"'choose' must be an object with 'message' and 'options'");let a=s;(!a.message||typeof a.message!="string")&&$(e,"'choose.message' is required and must be a string"),Array.isArray(a.options)||$(e,"'choose.options' is required and must be an array"),a.options.length===0&&$(e,"'choose.options' cannot be empty","At least one option is required");for(let l=0;l<a.options.length;l++){let c=a.options[l];(!c||typeof c!="object")&&$(e,`'choose.options[${l}]' must be an object with 'id' and 'label'`),(!c.id||typeof c.id!="string")&&$(e,`'choose.options[${l}].id' is required and must be a string`),(!c.label||typeof c.label!="string")&&$(e,`'choose.options[${l}].label' is required and must be a string`)}}if(i==="prompt"){if(t){let l=o.join(" \u2192 ");throw new Error(`Invalid workflow structure:
22
22
  - 'prompt' step is not allowed inside 'parallel' block (step ${e+1}, ${l})
23
- Reason: User input prompts cannot run in parallel`)}let i=r.prompt;(!i||typeof i!="object")&&k(e,"'prompt' must be an object with 'message' and 'as'");let a=i;(!a.message||typeof a.message!="string")&&k(e,"'prompt.message' is required and must be a string"),(!a.as||typeof a.as!="string")&&k(e,"'prompt.as' is required and must be a string","The 'as' field specifies the variable name to store the user's input")}if(s==="parallel"){let i=r.parallel;Array.isArray(i)||k(e,"'parallel' must be an array of steps"),i.length===0&&k(e,"'parallel' cannot be empty","At least one step is required");for(let a=0;a<i.length;a++){let l=i[a];(!l||typeof l!="object")&&k(e,`'parallel[${a}]' must be a valid step object`);let c=[...o,`branch ${a+1}`];wt(l,e,!0,c)}}if(s==="fail"){let i=r.fail;(!i||typeof i!="object")&&k(e,"'fail' must be an object with 'message'");let a=i;(!a.message||typeof a.message!="string")&&k(e,"'fail.message' is required and must be a string")}}function yt(r){if(!r||typeof r!="object")throw new Error(`Invalid workflow structure:
23
+ Reason: User input prompts cannot run in parallel`)}let s=r.prompt;(!s||typeof s!="object")&&$(e,"'prompt' must be an object with 'message' and 'as'");let a=s;(!a.message||typeof a.message!="string")&&$(e,"'prompt.message' is required and must be a string"),(!a.as||typeof a.as!="string")&&$(e,"'prompt.as' is required and must be a string","The 'as' field specifies the variable name to store the user's input")}if(i==="parallel"){let s=r.parallel;Array.isArray(s)||$(e,"'parallel' must be an array of steps"),s.length===0&&$(e,"'parallel' cannot be empty","At least one step is required");for(let a=0;a<s.length;a++){let l=s[a];(!l||typeof l!="object")&&$(e,`'parallel[${a}]' must be a valid step object`);let c=[...o,`branch ${a+1}`];Dt(l,e,!0,c)}}if(i==="fail"){let s=r.fail;(!s||typeof s!="object")&&$(e,"'fail' must be an object with 'message'");let a=s;(!a.message||typeof a.message!="string")&&$(e,"'fail.message' is required and must be a string")}}function Tt(r){if(!r||typeof r!="object")throw new Error(`Invalid workflow structure:
24
24
  - Workflow must be an object`);let e=r;if("name"in e&&e.name!==void 0&&typeof e.name!="string")throw new Error(`Invalid workflow structure:
25
25
  - 'name' must be a string`);if("shell"in e&&e.shell!==void 0){if(!Array.isArray(e.shell))throw new Error(`Invalid workflow structure:
26
26
  - 'shell' must be an array`);if(e.shell.length===0)throw new Error(`Invalid workflow structure:
@@ -31,49 +31,139 @@ Total execution time: ${i}`)),await o.save(),o.reset()}isStepSuccessful(e,t){ret
31
31
  - 'steps' must be an array`);if(e.steps.length===0)throw new Error(`Invalid workflow structure:
32
32
  - 'steps' cannot be empty
33
33
  Reason: Workflow must have at least one step`);for(let t=0;t<e.steps.length;t++){let o=e.steps[t];if(!o||typeof o!="object")throw new Error(`Invalid workflow structure:
34
- - Step ${t+1} must be an object`);wt(o,t)}}function wo(r,e){try{let t=e;for(let s of r)if(typeof s!="symbol")if(t&&typeof t=="object")t=t[s];else return null;if(!t||typeof t!="object")return null;let n=Object.keys(t);if(n.length>0){let s=["run","choose","prompt","parallel","fail"];if(!n.some(a=>s.includes(a)))return`Unknown step type. Found keys: [${n.join(", ")}]. Valid types: run, choose, prompt, parallel, fail`}return null}catch{return null}}function Ve(r){let e=r;return"choose"in e&&(e.choose===null||e.choose===void 0)&&"message"in e&&"options"in e?{choose:{message:e.message,options:e.options,as:e.as},when:e.when}:"prompt"in e&&(e.prompt===null||e.prompt===void 0)&&"message"in e&&"as"in e?{prompt:{message:e.message,as:e.as,default:e.default,validate:e.validate},when:e.when}:"parallel"in e&&Array.isArray(e.parallel)?{...e,parallel:e.parallel.map(t=>Ve(t))}:r}var ve=class{parse(e){let t;try{t=(0,ht.parse)(e)}catch(o){throw new Error(`Invalid YAML format: ${o instanceof Error?o.message:String(o)}`)}if(t&&typeof t=="object"&&"steps"in t){let o=t;Array.isArray(o.steps)&&(o.steps=o.steps.map(n=>Ve(n)))}yt(t);try{return Be(t)}catch(o){if(o instanceof He.ZodError){let n=o.issues.map(s=>gt(s,t)).filter(s=>s!==null).join(`
34
+ - Step ${t+1} must be an object`);Dt(o,t)}}function Zo(r,e){try{let t=e;for(let i of r)if(typeof i!="symbol")if(t&&typeof t=="object")t=t[i];else return null;if(!t||typeof t!="object")return null;let n=Object.keys(t);if(n.length>0){let i=["run","choose","prompt","parallel","fail"];if(!n.some(a=>i.includes(a)))return`Unknown step type. Found keys: [${n.join(", ")}]. Valid types: run, choose, prompt, parallel, fail`}return null}catch{return null}}function Ge(r){let e=r;return"choose"in e&&(e.choose===null||e.choose===void 0)&&"message"in e&&"options"in e?{choose:{message:e.message,options:e.options,as:e.as},when:e.when}:"prompt"in e&&(e.prompt===null||e.prompt===void 0)&&"message"in e&&"as"in e?{prompt:{message:e.message,as:e.as,default:e.default,validate:e.validate},when:e.when}:"parallel"in e&&Array.isArray(e.parallel)?{...e,parallel:e.parallel.map(t=>Ge(t))}:r}var Ee=class{parse(e){let t;try{t=(0,Pt.parse)(e)}catch(o){throw new Error(`Invalid YAML format: ${o instanceof Error?o.message:String(o)}`)}if(t&&typeof t=="object"&&"steps"in t){let o=t;Array.isArray(o.steps)&&(o.steps=o.steps.map(n=>Ge(n)))}Tt(t);try{return Ue(t)}catch(o){if(o instanceof qe.ZodError){let n=o.issues.map(i=>Ct(i,t)).filter(i=>i!==null).join(`
35
35
  `);throw new Error(`Invalid workflow structure:
36
36
  ${n}`)}throw o}}extractStepLineNumbers(e){let t=new Map,o=e.split(`
37
- `),n=0,s=!1;for(let i=0;i<o.length;i++){let a=o[i].trim();if(a==="steps:"||a.startsWith("steps:")){s=!0;continue}s&&a.startsWith("-")&&t.set(n++,i+1)}return t}},_e=class{parse(e){let t;try{t=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON format: ${o instanceof Error?o.message:String(o)}`)}if(t&&typeof t=="object"&&"steps"in t){let o=t;Array.isArray(o.steps)&&(o.steps=o.steps.map(n=>Ve(n)))}yt(t);try{return Be(t)}catch(o){if(o instanceof He.ZodError){let n=o.issues.map(s=>gt(s,t)).filter(s=>s!==null).join(`
37
+ `),n=0,i=!1;for(let s=0;s<o.length;s++){let a=o[s].trim();if(a==="steps:"||a.startsWith("steps:")){i=!0;continue}i&&a.startsWith("-")&&t.set(n++,s+1)}return t}},Je=class{parse(e){let t;try{t=JSON.parse(e)}catch(o){throw new Error(`Invalid JSON format: ${o instanceof Error?o.message:String(o)}`)}if(t&&typeof t=="object"&&"steps"in t){let o=t;Array.isArray(o.steps)&&(o.steps=o.steps.map(n=>Ge(n)))}Tt(t);try{return Ue(t)}catch(o){if(o instanceof qe.ZodError){let n=o.issues.map(i=>Ct(i,t)).filter(i=>i!==null).join(`
38
38
  `);throw new Error(`Invalid workflow structure:
39
39
  ${n}`)}throw o}}extractStepLineNumbers(e){let t=new Map,o=e.split(`
40
- `),n=0,s=!1,i=!1;for(let a=0;a<o.length;a++){let c=o[a].trim();if(c.startsWith('"steps"')||c.startsWith("'steps'")){s=!0,c.includes("[")&&(i=!0);continue}if(s&&c==="["){i=!0;continue}if(i&&c==="]"){i=!1,s=!1;continue}i&&c.startsWith("{")&&t.set(n++,a+1)}return t}};function ue(r){switch(r.toLowerCase().split(".").pop()){case"yaml":case"yml":return new ve;case"json":return new _e;default:return new ve}}var kt=require("fs/promises"),xt=require("path"),xe=y(require("boxen"),1),L=y(require("chalk"),1),Ue=y(require("node-cron"),1);le();var ne=require("fs/promises"),St=require("os"),ze=require("path"),vt=(0,ze.join)((0,St.homedir)(),".pipeliner","schedules"),bt=(0,ze.join)(vt,"schedules.json"),j=class{async loadSchedules(){try{let e=await(0,ne.readFile)(bt,"utf-8");return JSON.parse(e).schedules||[]}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async saveSchedules(e){await(0,ne.mkdir)(vt,{recursive:!0}),await(0,ne.writeFile)(bt,JSON.stringify({schedules:e},null,2),"utf-8")}async addSchedule(e){let t=await this.loadSchedules(),o=Math.random().toString(36).slice(2,10),n=new Date().toISOString(),s={id:o,createdAt:n,...e};return t.push(s),await this.saveSchedules(t),s}async removeSchedule(e){let t=await this.loadSchedules(),o=t.length,n=t.filter(s=>s.id!==e);return n.length===o?!1:(await this.saveSchedules(n),!0)}async updateLastRun(e){let t=await this.loadSchedules(),o=t.find(n=>n.id===e);o&&(o.lastRun=new Date().toISOString(),await this.saveSchedules(t))}async toggleSchedule(e,t){let o=await this.loadSchedules(),n=o.find(s=>s.id===e);return n?(n.enabled=t,await this.saveSchedules(o),!0):!1}async getSchedule(e){return(await this.loadSchedules()).find(o=>o.id===e)}};var yo=/^([+-])?(\d{1,2})(?::(\d{2}))?$/;function bo(r){let e=r.trim();if(e===""||e==="0"||e==="+0"||e==="-0")return 0;let t=e.match(yo);if(!t)return null;let o=t[1],n=parseInt(t[2],10);if(n>14)return null;let i=o==="-"?-n:n;return i<-12||i>14?null:i}function So(r){if(r===0)return"UTC";let e=r>0?"-":"+",t=Math.abs(r);return`Etc/GMT${e}${t}`}function ke(r){if(!r?.trim())return;let e=bo(r);if(e!==null)return So(e)}var z=class{scheduleManager;tasks=new Map;startOptions;constructor(){this.scheduleManager=new j}async start(e=!1,t){if(this.startOptions=t,!e&&await H()){let n=await $();throw new Error(`Scheduler daemon is already running (PID: ${n.pid}). Use "tp schedule stop" to stop it first.`)}if(e)console.log("\u{1F680} Starting scheduler daemon in background...");else{let n=L.default.bold("\u{1F680} Starting workflow scheduler...");console.log((0,xe.default)(n,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"}))}if(await this.reload(),e){if(!process.env.TP_DAEMON_MODE){let n=[L.default.green("\u2713 Scheduler daemon started"),"",L.default.gray(`PID: ${process.pid}`),L.default.dim(" tp schedule stop stop daemon"),L.default.dim(" tp schedule status check status")].join(`
41
- `);console.log(`${(0,xe.default)(n,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},borderColor:"green"})}
42
- `)}}else{let n=[L.default.green("\u2713 Scheduler is running"),L.default.dim(" Press Ctrl+C to stop")].join(`
43
- `);console.log((0,xe.default)(n,{borderStyle:"round",padding:{top:0,bottom:0,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"green"}))}let o=async()=>{e||console.log(`
44
- \u23F9 Stopping scheduler...`),this.stop(),await ae(),e||process.exit(0)};process.on("SIGINT",o),process.on("SIGTERM",o),e&&process.stdin.destroy()}async reload(){this.stop();let t=(await this.scheduleManager.loadSchedules()).filter(o=>o.enabled);if(t.length===0){console.log(L.default.gray(` No enabled schedules to load.
45
- `));return}for(let o of t)try{this.startSchedule(o)}catch(n){console.error(L.default.red(` \u2717 Failed to start schedule ${o.id}:`),n)}}startSchedule(e){if(!Ue.default.validate(e.cron)){console.error(` \u2717 Invalid cron expression for schedule ${e.id}: ${e.cron}`);return}let t={},o=ke(e.timezone);o&&(t.timezone=o);let n;try{n=Ue.default.schedule(e.cron,async()=>{await this.executeSchedule(e)},t)}catch(s){throw console.error(` \u2717 Cron schedule failed for ${e.id} (timezone: ${o??"local"}).`,s instanceof Error?s.message:s),s}this.tasks.set(e.id,n),this.startOptions?.onScheduleStarted?.(e)}async executeSchedule(e){let t=e.name??e.workflowPath;e.silent||(console.log(`
46
- \u23F0 Running scheduled workflow: ${t}`),console.log(` Time: ${new Date().toISOString()}`),e.profile&&console.log(` Profile: ${e.profile}`));try{let o=(0,xt.resolve)(e.workflowPath),n=ue(o),s=await(0,kt.readFile)(o,"utf-8"),i=n.parse(s),a=new re,l={};if(e.profile){if(!i.profiles)throw new Error(`Profile "${e.profile}" not found: no profiles defined in workflow`);let c=i.profiles.find(f=>f.name===e.profile);if(!c)throw new Error(`Profile "${e.profile}" not found. Available profiles: ${i.profiles.map(f=>f.name).join(", ")}`);l.profileVars=c.var}await a.execute(i,l),await this.scheduleManager.updateLastRun(e.id),e.silent||console.log(`\u2713 Scheduled workflow completed: ${t}
40
+ `),n=0,i=!1,s=!1;for(let a=0;a<o.length;a++){let c=o[a].trim();if(c.startsWith('"steps"')||c.startsWith("'steps'")){i=!0,c.includes("[")&&(s=!0);continue}if(i&&c==="["){s=!0;continue}if(s&&c==="]"){s=!1,i=!1;continue}s&&c.startsWith("{")&&t.set(n++,a+1)}return t}};function ce(r){switch(r.toLowerCase().split(".").pop()){case"yaml":case"yml":return new Ee;case"json":return new Je;default:return new Ee}}var jt=require("fs/promises"),At=require("path"),Ce=b(require("boxen"),1),B=b(require("chalk"),1),Xe=b(require("node-cron"),1);te();var ue=require("fs/promises"),Mt=require("os"),Ze=require("path"),Nt=(0,Ze.join)((0,Mt.homedir)(),".pipeliner","schedules"),It=(0,Ze.join)(Nt,"schedules.json"),A=class{async loadSchedules(){try{let e=await(0,ue.readFile)(It,"utf-8");return JSON.parse(e).schedules||[]}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async saveSchedules(e){await(0,ue.mkdir)(Nt,{recursive:!0}),await(0,ue.writeFile)(It,JSON.stringify({schedules:e},null,2),"utf-8")}async addSchedule(e){let t=await this.loadSchedules(),o=Math.random().toString(36).slice(2,10),n=new Date().toISOString(),i={id:o,createdAt:n,...e};return t.push(i),await this.saveSchedules(t),i}async removeSchedule(e){let t=await this.loadSchedules(),o=t.length,n=t.filter(i=>i.id!==e);return n.length===o?!1:(await this.saveSchedules(n),!0)}async updateLastRun(e){let t=await this.loadSchedules(),o=t.find(n=>n.id===e);o&&(o.lastRun=new Date().toISOString(),await this.saveSchedules(t))}async toggleSchedule(e,t){let o=await this.loadSchedules(),n=o.find(i=>i.id===e);return n?(n.enabled=t,await this.saveSchedules(o),!0):!1}async getSchedule(e){return(await this.loadSchedules()).find(o=>o.id===e)}};var Xo=/^([+-])?(\d{1,2})(?::(\d{2}))?$/;function Ko(r){let e=r.trim();if(e===""||e==="0"||e==="+0"||e==="-0")return 0;let t=e.match(Xo);if(!t)return null;let o=t[1],n=parseInt(t[2],10);if(n>14)return null;let s=o==="-"?-n:n;return s<-12||s>14?null:s}function Qo(r){if(r===0)return"UTC";let e=r>0?"-":"+",t=Math.abs(r);return`Etc/GMT${e}${t}`}function Pe(r){if(!r?.trim())return;let e=Ko(r);if(e!==null)return Qo(e)}var z=class{scheduleManager;tasks=new Map;startOptions;constructor(){this.scheduleManager=new A}async start(e=!1,t){if(this.startOptions=t,!e&&await W()){let n=await P();throw new Error(`Scheduler daemon is already running (PID: ${n.pid}). Use "tp schedule stop" to stop it first.`)}if(e)console.log("\u{1F680} Starting scheduler daemon in background...");else{let n=B.default.bold("\u{1F680} Starting workflow scheduler...");console.log((0,Ce.default)(n,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"}))}if(await this.reload(),e){if(!process.env.TP_DAEMON_MODE){let n=[B.default.green("\u2713 Scheduler daemon started"),"",B.default.gray(`PID: ${process.pid}`),B.default.dim(" tp schedule stop stop daemon"),B.default.dim(" tp schedule status check status")].join(`
41
+ `);console.log(`${(0,Ce.default)(n,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},borderColor:"green"})}
42
+ `)}}else{let n=[B.default.green("\u2713 Scheduler is running"),B.default.dim(" Press Ctrl+C to stop")].join(`
43
+ `);console.log((0,Ce.default)(n,{borderStyle:"round",padding:{top:0,bottom:0,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"green"}))}let o=async()=>{e||console.log(`
44
+ \u23F9 Stopping scheduler...`),this.stop(),await me(),e||process.exit(0)};process.on("SIGINT",o),process.on("SIGTERM",o),e&&process.stdin.destroy()}async reload(){this.stop();let t=(await this.scheduleManager.loadSchedules()).filter(o=>o.enabled);if(t.length===0){console.log(B.default.gray(` No enabled schedules to load.
45
+ `));return}for(let o of t)try{this.startSchedule(o)}catch(n){console.error(B.default.red(` \u2717 Failed to start schedule ${o.id}:`),n)}}startSchedule(e){if(!Xe.default.validate(e.cron)){console.error(` \u2717 Invalid cron expression for schedule ${e.id}: ${e.cron}`);return}let t={},o=Pe(e.timezone);o&&(t.timezone=o);let n;try{n=Xe.default.schedule(e.cron,async()=>{await this.executeSchedule(e)},t)}catch(i){throw console.error(` \u2717 Cron schedule failed for ${e.id} (timezone: ${o??"local"}).`,i instanceof Error?i.message:i),i}this.tasks.set(e.id,n),this.startOptions?.onScheduleStarted?.(e)}async executeSchedule(e){let t=e.name??e.workflowPath;e.silent||(console.log(`
46
+ \u23F0 Running scheduled workflow: ${t}`),console.log(` Time: ${new Date().toISOString()}`),e.profile&&console.log(` Profile: ${e.profile}`));try{let o=(0,At.resolve)(e.workflowPath),n=ce(o),i=await(0,jt.readFile)(o,"utf-8"),s=n.parse(i),a=new le,l={};if(e.profile){if(!s.profiles)throw new Error(`Profile "${e.profile}" not found: no profiles defined in workflow`);let c=s.profiles.find(d=>d.name===e.profile);if(!c)throw new Error(`Profile "${e.profile}" not found. Available profiles: ${s.profiles.map(d=>d.name).join(", ")}`);l.profileVars=c.var}await a.execute(s,l),await this.scheduleManager.updateLastRun(e.id),e.silent||console.log(`\u2713 Scheduled workflow completed: ${t}
47
47
  `)}catch(o){e.silent||(console.error(`\u2717 Scheduled workflow failed: ${t}`),console.error(` Error: ${o instanceof Error?o.message:String(o)}
48
- `))}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async stopDaemon(){let e=await $();if(!e.running||!e.pid)return!1;let t=e.pid;try{if(process.kill(t,"SIGTERM"),await new Promise(o=>setTimeout(o,1e3)),await H()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(o=>setTimeout(o,500))}return await ae(),!0}catch{return await ae(),!1}}};var Ot=require("child_process"),Ee=require("fs"),Ft=require("fs/promises"),R=require("path"),Re=y(require("boxen"),1),m=y(require("chalk"),1),Bt=require("commander"),Pe=y(require("dayjs"),1),Ce=y(require("inquirer"),1),pe=y(require("log-update"),1),Wt=y(require("node-cron"),1);le();var Et=require("fs/promises"),Rt=require("path"),Pt=require("yaml"),Ct=require("zod");var C=require("zod"),vo=C.z.object({name:C.z.string().min(1,"Schedule name must be non-empty"),cron:C.z.string().min(1,"Cron expression is required"),workflow:C.z.string().min(1,"Workflow path is required"),baseDir:C.z.string().optional(),timezone:C.z.union([C.z.string(),C.z.number()]).transform(String).optional(),silent:C.z.boolean().optional(),profile:C.z.string().optional()}),ko=C.z.object({schedules:C.z.array(vo).min(1,"Schedule file must have at least one schedule")});function $t(r){return ko.parse(r)}async function Dt(r){let e=await(0,Et.readFile)(r,"utf-8"),t=(0,Rt.extname)(r).toLowerCase(),o;try{if(t===".yaml"||t===".yml")o=(0,Pt.parse)(e);else if(t===".json")o=JSON.parse(e);else throw new Error(`Unsupported file format: ${t}. Use .yaml, .yml, or .json`)}catch(n){if(n instanceof Error&&n.message.startsWith("Unsupported"))throw n;let s=t===".json"?"JSON":"YAML";throw new Error(`Invalid ${s} format: ${n instanceof Error?n.message:String(n)}`)}try{return $t(o)}catch(n){if(n instanceof Ct.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).join(`
48
+ `))}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async stopDaemon(){let e=await P();if(!e.running||!e.pid)return!1;let t=e.pid;try{if(process.kill(t,"SIGTERM"),await new Promise(o=>setTimeout(o,1e3)),await W()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(o=>setTimeout(o,500))}return await me(),!0}catch{return await me(),!1}}};var Ke=b(require("boxen"),1),y=b(require("chalk"),1),Lt=b(require("dayjs"),1);function Ot(r,e){console.log();let t=r.records.reduce((l,c)=>l+c.duration,0),o=r.records.filter(l=>l.status==="success").length,n=r.records.filter(l=>l.status==="failure").length,i=(0,Lt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),s=ne(t),a=[y.default.bold("Workflow Execution History"),"",`${y.default.cyan("File:")} ${e}`,`${y.default.cyan("Started:")} ${i}`,`${y.default.cyan("Total Duration:")} ${s}`,`${y.default.cyan("Total Steps:")} ${r.records.length}`,`${y.default.green("\u2713 Successful:")} ${o}`,n>0?`${y.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
49
+ `);console.log((0,Ke.default)(a,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"})),r.records.forEach((l,c)=>{er(l,c+1,r.records.length)}),console.log()}function er(r,e,t){let o=tr(r.step),n=or(r),i=r.status==="success"?y.default.green("\u2713"):y.default.red("\u2717"),s=r.status==="success"?y.default.green("Success"):y.default.red("Failed"),a=ne(r.duration),l=[`${i} ${y.default.bold(`Step ${e}/${t}`)} - ${y.default.cyan(o)}`,`${y.default.gray("Duration:")} ${a} | ${y.default.gray("Status:")} ${s}`,"",y.default.white(n)].join(`
50
+ `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),rr(r.output)&&nr(r.output)}function tr(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function or(r){let e=r.step,t=[];if("run"in e){let o=r.resolvedCommand,n=o??e.run;t.push(`Command: ${y.default.yellow(n)}`),o&&o!==e.run&&t.push(`${y.default.gray("Template:")} ${y.default.gray(e.run)}`)}else if("choose"in e){if(t.push(`Message: ${y.default.yellow(e.choose.message)}`),r.choiceValue!==void 0){let o=e.choose.options.find(n=>n.id===r.choiceValue)?.label??r.choiceValue;t.push(`${y.default.gray("Selected:")} ${y.default.cyan(r.choiceValue)}${o!==r.choiceValue?` (${o})`:""}`)}}else"prompt"in e?(t.push(`Message: ${y.default.yellow(e.prompt.message)} | Variable: ${y.default.cyan(e.prompt.as)}`),r.promptValue!==void 0&&t.push(`${y.default.gray("Entered:")} ${y.default.cyan(String(r.promptValue))}`)):"parallel"in e?t.push(`Parallel execution with ${e.parallel.length} branches`):"fail"in e?t.push(`Error: ${y.default.red(e.fail.message)}`):t.push("Unknown step type");return t.join(`
51
+ `)}function rr(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function nr(r){if(r.stdout.length>0){let e=r.stdout.map(t=>y.default.gray(` ${t}`)).join(`
52
+ `);console.log(y.default.green(" Output:")),console.log(e)}if(r.stderr.length>0){let e=r.stderr.map(t=>y.default.gray(` ${t}`)).join(`
53
+ `);console.log(y.default.red(" Errors:")),console.log(e)}}var co=require("commander");var Gt=require("child_process"),Te=require("fs"),Zt=require("fs/promises"),D=require("path"),Xt=b(require("boxen"),1),x=b(require("chalk"),1),Ie=b(require("inquirer"),1),Kt=b(require("node-cron"),1);te();var Bt=require("fs/promises"),Vt=require("path"),Wt=require("yaml"),Ht=require("zod");var N=require("zod"),sr=N.z.object({name:N.z.string().min(1,"Schedule name must be non-empty"),cron:N.z.string().min(1,"Cron expression is required"),workflow:N.z.string().min(1,"Workflow path is required"),baseDir:N.z.string().optional(),timezone:N.z.union([N.z.string(),N.z.number()]).transform(String).optional(),silent:N.z.boolean().optional(),profile:N.z.string().optional()}),ir=N.z.object({schedules:N.z.array(sr).min(1,"Schedule file must have at least one schedule")});function Ft(r){return ir.parse(r)}async function _t(r){let e=await(0,Bt.readFile)(r,"utf-8"),t=(0,Vt.extname)(r).toLowerCase(),o;try{if(t===".yaml"||t===".yml")o=(0,Wt.parse)(e);else if(t===".json")o=JSON.parse(e);else throw new Error(`Unsupported file format: ${t}. Use .yaml, .yml, or .json`)}catch(n){if(n instanceof Error&&n.message.startsWith("Unsupported"))throw n;let i=t===".json"?"JSON":"YAML";throw new Error(`Invalid ${i} format: ${n instanceof Error?n.message:String(n)}`)}try{return Ft(o)}catch(n){if(n instanceof Ht.ZodError){let i=n.issues.map(s=>` - ${s.message} (${s.path.join(".")})`).join(`
49
54
  `);throw new Error(`Invalid schedule file structure:
50
- ${s}`)}throw n}}var Tt=y(require("boxen"),1),S=y(require("chalk"),1),It=y(require("cronstrue"),1),Ye=y(require("dayjs"),1),Je=y(require("node-cron"),1);function qe(r){try{return It.default.toString(r)}catch{return null}}function xo(r){if(!Je.default.validate(r.cron))return null;try{let e={},t=ke(r.timezone);t&&(e.timezone=t);let o=Je.default.createTask(r.cron,()=>{},e),n=o.getNextRun();return o.destroy(),n}catch{return null}}function G(r,e){let t=r,{daemonRunning:o,emphasizeState:n}=e,s=t.enabled?n?S.default.bold.green("ENABLED"):S.default.green("enabled"):n?S.default.bold.gray("DISABLED"):S.default.gray("disabled"),i=o&&t.enabled,a=i?S.default.green("\u25CF active"):S.default.gray("\u25CB inactive"),l=n?t.enabled?S.default.bold.green(" [ENABLED]"):S.default.bold.gray(" [DISABLED]"):"",c=S.default.bold(t.name??t.workflowPath),f=xo(t),g=f?(0,Ye.default)(f).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("\u2014"),h=t.lastRun?(0,Ye.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("never"),d=qe(t.cron),w=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,b=d?`${t.cron} ${S.default.dim(`\u2192 ${d}`)}`:t.cron,v=[[S.default.gray("Enabled"),s],[S.default.gray("Cron"),b],...w?[[S.default.gray("Timezone"),w]]:[],[S.default.gray("Workflow"),t.workflowPath],...t.profile?[[S.default.gray("Profile"),S.default.cyan(t.profile)]]:[],...t.silent?[[S.default.gray("Silent"),S.default.yellow("yes")]]:[],[S.default.gray("Last run"),h],[S.default.gray("Next run"),g]],E=[`${c} ${a}${l}`,...v.map(([B,W])=>` ${B.padEnd(10)} ${W}`)].join(`
51
- `);return(0,Tt.default)(E,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}var V=require("fs"),P=require("path"),Ge=require("url"),Mt={};function Nt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function jt(){return"0.3.5"}function $e(r){let e=r?(0,P.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,P.resolve)(e,"tp");try{if((0,V.existsSync)(n)&&(0,V.statSync)(n).isDirectory())return n}catch{}let s=(0,P.dirname)(e);if(s===e)break;e=s,o++}return null}function _t(){let r=new Bt.Command("schedule").description("Manage workflow schedules").action(async()=>{await At()});return r.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON). If no file given, select from nearest tp/schedules directory.").action(async e=>{await $o(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await Eo()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Mo()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await At()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Ro(e.daemon??!1)}),r.command("stop").description("Stop the scheduler daemon").action(async()=>{await Po()}),r.command("status").description('View daemon and schedule status (does not start the daemon). In live mode, Ctrl+C only exits the status view; the daemon keeps running if it was started with "tp schedule start -d".').option("-n, --no-follow","Show status once and exit (no live refresh)").action(async e=>{let t=e.follow!==!1;await To(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await Io()}),r}function Ze(r,e){let t=e.workflow;if((0,R.isAbsolute)(t))return t;let o=e.baseDir?(0,R.resolve)(e.baseDir):(0,R.dirname)(r);return(0,R.resolve)(o,t)}async function $o(r){let e=new j;if(!r){let l=$e();l||(console.error(m.default.red(`
52
- \u2717 No tp directory found`)),process.exit(1));let c=(0,R.join)(l,"schedules");(0,Ee.existsSync)(c)||(console.error(m.default.red(`
53
- \u2717 No schedules directory found at ${c}`)),process.exit(1));let g=(await(0,Ft.readdir)(c)).filter(b=>{let v=(0,R.extname)(b).toLowerCase();return[".yaml",".yml",".json"].includes(v)});g.length===0&&(console.error(m.default.red(`
54
- \u2717 No schedule files found in ${c}`)),process.exit(1));let h=g.map(b=>({id:(0,R.join)(c,b),label:b}));r=(await new I(!0).prompt("Select a schedule file to add",h)).id}let t=(0,R.resolve)(r);(0,Ee.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let o;try{o=await Dt(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let n=o.schedules.filter(l=>!Wt.default.validate(l.cron));if(n.length>0){console.error("\u2717 Invalid cron expression(s):");for(let l of n)console.error(` - ${l.name}: "${l.cron}"`);process.exit(1)}let s=o.schedules.filter(l=>{let c=Ze(t,l);return!(0,Ee.existsSync)(c)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of s){let c=Ze(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
55
+ ${i}`)}throw n}}var zt=b(require("boxen"),1),k=b(require("chalk"),1),Ut=b(require("cronstrue"),1),Qe=b(require("dayjs"),1),et=b(require("node-cron"),1);function tt(r){try{return Ut.default.toString(r)}catch{return null}}function ar(r){if(!et.default.validate(r.cron))return null;try{let e={},t=Pe(r.timezone);t&&(e.timezone=t);let o=et.default.createTask(r.cron,()=>{},e),n=o.getNextRun();return o.destroy(),n}catch{return null}}function U(r,e){let t=r,{daemonRunning:o,emphasizeState:n}=e,i=t.enabled?n?k.default.bold.green("ENABLED"):k.default.green("enabled"):n?k.default.bold.gray("DISABLED"):k.default.gray("disabled"),s=o&&t.enabled,a=s?k.default.green("\u25CF active"):k.default.gray("\u25CB inactive"),l=n?t.enabled?k.default.bold.green(" [ENABLED]"):k.default.bold.gray(" [DISABLED]"):"",c=k.default.bold(t.name??t.workflowPath),d=ar(t),m=d?(0,Qe.default)(d).format("YYYY-MM-DD HH:mm:ss"):k.default.dim("\u2014"),f=t.lastRun?(0,Qe.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):k.default.dim("never"),p=tt(t.cron),h=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,w=h??"local",v=p?`${t.cron} ${k.default.dim(`\u2192 ${p} (${w})`)}`:t.cron,C=[[k.default.gray("Enabled"),i],[k.default.gray("Cron"),v],[k.default.gray("Timezone"),h??k.default.dim("local")],[k.default.gray("Workflow"),t.workflowPath],...t.profile?[[k.default.gray("Profile"),k.default.cyan(t.profile)]]:[],...t.silent?[[k.default.gray("Silent"),k.default.yellow("yes")]]:[],[k.default.gray("Last run"),f],[k.default.gray("Next run"),m]],R=[`${c} ${a}${l}`,...C.map(([T,G])=>` ${T.padEnd(10)} ${G}`)].join(`
56
+ `);return(0,zt.default)(R,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:s?"green":"gray"})}var H=require("fs"),M=require("path"),ot=require("url"),Yt={};function Jt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function qt(){return"0.3.6"}function De(r){let e=r?(0,M.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,M.resolve)(e,"tp");try{if((0,H.existsSync)(n)&&(0,H.statSync)(n).isDirectory())return n}catch{}let i=(0,M.dirname)(e);if(i===e)break;e=i,o++}return null}function rt(r,e){let t=e.workflow;if((0,D.isAbsolute)(t))return t;let o=e.baseDir?(0,D.resolve)(e.baseDir):(0,D.dirname)(r);return(0,D.resolve)(o,t)}function Qt(r,e="plain"){let t=r.name??"(no alias)",o=(0,D.basename)(r.workflowPath),n=tt(r.cron)??r.cron,i=e==="color"?r.enabled?x.default.green("Enabled"):x.default.dim("Disabled"):r.enabled?"\u2713":"\u2717";return`${t} \xB7 ${o} \xB7 ${r.cron} \xB7 ${n} \xB7 ${i}`}async function eo(r){let e=new A;if(!r){let l=De();l||(console.error(x.default.red(`
57
+ \u2717 No tp directory found`)),process.exit(1));let c=(0,D.join)(l,"schedules");(0,Te.existsSync)(c)||(console.error(x.default.red(`
58
+ \u2717 No schedules directory found at ${c}`)),process.exit(1));let m=(await(0,Zt.readdir)(c)).filter(w=>{let v=(0,D.extname)(w).toLowerCase();return[".yaml",".yml",".json"].includes(v)});m.length===0&&(console.error(x.default.red(`
59
+ \u2717 No schedule files found in ${c}`)),process.exit(1));let f=m.map(w=>({id:(0,D.join)(c,w),label:w}));r=(await new I(!0).prompt("Select a schedule file to add",f)).id}let t=(0,D.resolve)(r);(0,Te.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let o;try{o=await _t(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let n=o.schedules.filter(l=>!Kt.default.validate(l.cron));if(n.length>0){console.error("\u2717 Invalid cron expression(s):");for(let l of n)console.error(` - ${l.name}: "${l.cron}"`);process.exit(1)}let i=o.schedules.filter(l=>{let c=rt(t,l);return!(0,Te.existsSync)(c)});if(i.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of i){let c=rt(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
55
60
  Found ${o.schedules.length} schedule(s) in file.
56
- `);let i=[];for(let l of o.schedules){let{alias:c}=await Ce.default.prompt([{type:"input",name:"alias",message:`Alias for "${l.name}" (press Enter to use as-is):`,default:l.name}]),f=await e.addSchedule({name:c,workflowPath:Ze(t,l),cron:l.cron,enabled:!0,timezone:l.timezone,silent:l.silent,profile:l.profile});i.push(f)}let a=await $();console.log(`
57
- \u2713 Added ${i.length} schedule(s) successfully
58
- `);for(let l of i)console.log(G(l,{daemonRunning:a.running}));console.log(m.default.dim(' Tip: Run "tp schedule start" to start the scheduler daemon'))}function Ht(r,e="plain"){let t=r.name??"(no alias)",o=(0,R.basename)(r.workflowPath),n=qe(r.cron)??r.cron,s=e==="color"?r.enabled?m.default.green("Enabled"):m.default.dim("Disabled"):r.enabled?"\u2713":"\u2717";return`${t} \xB7 ${o} \xB7 ${r.cron} \xB7 ${n} \xB7 ${s}`}async function Eo(){let r=new j,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(c=>({id:c.id,label:Ht(c)})),s=(await new I(!0).prompt("Select schedule to remove:",t)).id,i=e.find(c=>c.id===s),{confirm:a}=await Ce.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!a){console.log("Cancelled");return}let l=await r.removeSchedule(s);if(l&&i){let c=await $();console.log(`
61
+ `);let s=[];for(let l of o.schedules){let{alias:c}=await Ie.default.prompt([{type:"input",name:"alias",message:`Alias for "${l.name}" (press Enter to use as-is):`,default:l.name}]),d=await e.addSchedule({name:c,workflowPath:rt(t,l),cron:l.cron,enabled:!0,timezone:l.timezone,silent:l.silent,profile:l.profile});s.push(d)}let a=await P();console.log(`
62
+ \u2713 Added ${s.length} schedule(s) successfully
63
+ `);for(let l of s)console.log(U(l,{daemonRunning:a.running}));console.log(x.default.dim(' Tip: Run "tp schedule start" to start the scheduler daemon'))}async function to(){let r=new A,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(c=>({id:c.id,label:Qt(c)})),i=(await new I(!0).prompt("Select schedule to remove:",t)).id,s=e.find(c=>c.id===i),{confirm:a}=await Ie.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!a){console.log("Cancelled");return}let l=await r.removeSchedule(i);if(l&&s){let c=await P();console.log(`
59
64
  \u2713 Schedule removed
60
- `),console.log(G(i,{daemonRunning:c.running}))}else console.log(l?"\u2713 Schedule removed successfully":"\u2717 Schedule not found")}async function At(){let e=await new j().loadSchedules();if(e.length===0){let i=[m.default.gray("No schedules registered."),"",m.default.dim(" tp schedule add <schedule.yaml> add from a schedule file")].join(`
65
+ `),console.log(U(s,{daemonRunning:c.running}))}else console.log(l?"\u2713 Schedule removed successfully":"\u2717 Schedule not found")}async function nt(){let e=await new A().loadSchedules();if(e.length===0){let s=[x.default.gray("No schedules registered."),"",x.default.dim(" tp schedule add <schedule.yaml> add from a schedule file")].join(`
61
66
  `);console.log(`
62
- ${(0,Re.default)(i,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"})}
63
- `);return}let t=await $(),o=t.running?m.default.green("\u25CF running"):m.default.gray("\u25CB stopped"),n=e.filter(i=>i.enabled).length,s=m.default.bold("\u{1F4C5} Workflow Schedules");console.log(s),console.log([m.default.gray(" Daemon: "),o,m.default.gray(` \xB7 Schedules: ${n}/${e.length} enabled`)].join(""));for(let i of e)console.log(G(i,{daemonRunning:t.running}));console.log(m.default.dim(" Tip: tp schedule start \u2014 run scheduler daemon; tp schedule status \u2014 view live status"))}async function Ro(r){if(await H()){let e=await $();console.error(`\u2717 Scheduler daemon is already running (PID: ${e.pid})`),console.error(' Run "tp schedule stop" to stop it first'),process.exit(1)}if(r)if(process.env.TP_DAEMON_MODE==="true")try{let{saveDaemonPid:e}=await Promise.resolve().then(()=>(le(),tt));await e(),await new z().start(!0),await new Promise(()=>{})}catch(e){await Me(e instanceof Error?e:new Error(String(e))),process.exit(1)}else{let e=process.argv.slice(1);(0,Ot.spawn)(process.argv[0],e,{detached:!0,stdio:"ignore",env:{...process.env,TP_DAEMON_MODE:"true"}}).unref();let o=3,n=800,s=!1;for(let i=0;i<o;i++)if(await new Promise(a=>setTimeout(a,n)),await H()){s=!0;break}if(s){let i=await $();console.log(`\u2713 Scheduler daemon started in background (PID: ${i.pid})`),console.log(' Run "tp schedule stop" to stop the daemon'),console.log(' Run "tp schedule status" to check daemon status')}else{console.error("\u2717 Failed to start scheduler daemon");let i=await je();i?(console.error(m.default.dim(" Last error from daemon:")),console.error(m.default.red(i.split(`
67
+ ${(0,Xt.default)(s,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"})}
68
+ `);return}let t=await P(),o=t.running?x.default.green("\u25CF running"):x.default.gray("\u25CB stopped"),n=e.filter(s=>s.enabled).length,i=x.default.bold("\u{1F4C5} Workflow Schedules");console.log(i),console.log([x.default.gray(" Daemon: "),o,x.default.gray(` \xB7 Schedules: ${n}/${e.length} enabled`)].join(""));for(let s of e)console.log(U(s,{daemonRunning:t.running}));console.log(x.default.dim(" Tip: tp schedule start \u2014 run scheduler daemon; tp schedule status \u2014 view live status"))}async function oo(r){if(await W()){let e=await P();console.error(`\u2717 Scheduler daemon is already running (PID: ${e.pid})`),console.error(' Run "tp schedule stop" to stop it first'),process.exit(1)}if(r)if(process.env.TP_DAEMON_MODE==="true")try{let{saveDaemonPid:e}=await Promise.resolve().then(()=>(te(),lt));await e(),await new z().start(!0),await new Promise(()=>{})}catch(e){await Le(e instanceof Error?e:new Error(String(e))),process.exit(1)}else{let e=process.argv.slice(1);(0,Gt.spawn)(process.argv[0],e,{detached:!0,stdio:"ignore",env:{...process.env,TP_DAEMON_MODE:"true"}}).unref();let o=3,n=800,i=!1;for(let s=0;s<o;s++)if(await new Promise(a=>setTimeout(a,n)),await W()){i=!0;break}if(i){let s=await P();console.log(`\u2713 Scheduler daemon started in background (PID: ${s.pid})`),console.log(' Run "tp schedule stop" to stop the daemon'),console.log(' Run "tp schedule status" to check daemon status')}else{console.error("\u2717 Failed to start scheduler daemon");let s=await Fe();s?(console.error(x.default.dim(" Last error from daemon:")),console.error(x.default.red(s.split(`
64
69
  `).map(a=>` ${a}`).join(`
65
- `)))):console.error(m.default.dim(` Check ${Ne()} for details`)),process.exit(1)}process.exit(0)}else await new z().start(!1,{onScheduleStarted:t=>console.log(G(t,{daemonRunning:!0}))}),await new Promise(()=>{})}async function Po(){let r=await $();if(!r.running){console.log("Scheduler daemon is not running");return}console.log(`Stopping scheduler daemon (PID: ${r.pid})...`);let t=await new z().stopDaemon();console.log(t?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}function Co(r){if(!r)return"Unknown";let e=(0,Pe.default)(r),o=(0,Pe.default)().diff(e,"second"),n=Math.floor(o/86400),s=Math.floor(o%86400/3600),i=Math.floor(o%3600/60),a=o%60,l=[];return n>0&&l.push(`${n}d`),s>0&&l.push(`${s}h`),i>0&&l.push(`${i}m`),(a>0||l.length===0)&&l.push(`${a}s`),l.join(" ")}function Do(r,e){return G(r,{daemonRunning:e})}async function Xe(){let r=await $(),t=await new j().loadSchedules(),o=[],n;if(r.running&&r.pid){let i=Co(r.startTime),a=r.startTime?(0,Pe.default)(r.startTime).format("YYYY-MM-DD HH:mm:ss"):"Unknown";n=[`${m.default.green("\u25CF")} ${m.default.green("active")} ${m.default.gray("(running)")}`,"",`${m.default.gray("Loaded:")} ${m.default.white(a)}`,`${m.default.gray("Active:")} ${m.default.green("active (running)")} since ${m.default.white(a)}`,`${m.default.gray("PID:")} ${m.default.white(r.pid.toString())}`,`${m.default.gray("Uptime:")} ${m.default.white(i)}`].join(`
66
- `)}else n=[`${m.default.red("\u25CF")} ${m.default.red("inactive")} ${m.default.gray("(dead)")}`,"",`${m.default.gray("Loaded:")} ${m.default.gray("not found")}`,`${m.default.gray("Active:")} ${m.default.red("inactive (dead)")}`].join(`
67
- `);let s=(0,Re.default)(n,{title:m.default.bold("task-pipeliner-scheduler.service"),titleAlignment:"left",borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:r.running?"green":"red"});if(o.push(s),t.length>0){let i=t.filter(l=>l.enabled).length,a=m.default.bold(`Schedules: ${i}/${t.length} enabled`);o.push(a);for(let l of t)o.push(Do(l,r.running))}else{let i=(0,Re.default)(m.default.gray("No schedules configured"),{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"});o.push(i)}return o.join(`
68
- `)}function Lt(){process.stdout.write("\x1B[2J\x1B[H")}async function To(r){if(r){let e=!0,t=()=>{e=!1,pe.default.done(),process.exit(0)};process.on("SIGINT",t),process.on("SIGTERM",t);let o=setInterval(async()=>{if(!e){clearInterval(o);return}try{let a=await Xe(),c=(await $()).running?m.default.gray(`
69
- Press Ctrl+C to exit this view (daemon keeps running in background)`):m.default.gray(`
70
- Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,pe.default)(`${a}${c}`)}catch(a){pe.default.done(),console.error("Error updating status:",a),clearInterval(o),process.exit(1)}},1e3);Lt();let n=await Xe(),i=(await $()).running?m.default.gray(`
71
- Press Ctrl+C to exit this view (daemon keeps running in background)`):m.default.gray(`
72
- Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,pe.default)(`${n}${i}`),await new Promise(()=>{})}else{Lt();let e=await Xe(),o=(await $()).running?"":m.default.gray(`
70
+ `)))):console.error(x.default.dim(` Check ${Oe()} for details`)),process.exit(1)}process.exit(0)}else await new z().start(!1,{onScheduleStarted:t=>console.log(U(t,{daemonRunning:!0}))}),await new Promise(()=>{})}async function ro(){let r=await P();if(!r.running){console.log("Scheduler daemon is not running");return}console.log(`Stopping scheduler daemon (PID: ${r.pid})...`);let t=await new z().stopDaemon();console.log(t?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}async function no(){let r=new A,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(f=>({id:f.id,label:Qt(f,"color")})),i=(await new I(!0).prompt("Select schedule to toggle:",t)).id,s=e.find(f=>f.id===i);if(!s){console.log("\u2717 Schedule not found");return}let a=!s.enabled;await r.toggleSchedule(i,a);let l=await P(),c={...s,enabled:a},d=a?x.default.bold.green("ENABLED"):x.default.bold.gray("DISABLED"),m=a?x.default.dim(" (will run at the times shown below)"):x.default.dim(" (will not run until you enable it again)");console.log(`
71
+ \u2713 Schedule is now ${d}${m}
72
+ `),console.log(U(c,{daemonRunning:l.running,emphasizeState:!0}))}async function so(){let r=new A,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:t}=await Ie.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to remove all ${e.length} schedule(s)?`,default:!1}]);if(!t){console.log("Cancelled");return}await r.saveSchedules([]),console.log(`\u2713 Removed all ${e.length} schedule(s)`)}var st=b(require("boxen"),1),S=b(require("chalk"),1),Me=b(require("dayjs"),1),he=b(require("log-update"),1);te();function lr(r){if(!r)return"Unknown";let e=(0,Me.default)(r),o=(0,Me.default)().diff(e,"second"),n=Math.floor(o/86400),i=Math.floor(o%86400/3600),s=Math.floor(o%3600/60),a=o%60,l=[];return n>0&&l.push(`${n}d`),i>0&&l.push(`${i}h`),s>0&&l.push(`${s}m`),(a>0||l.length===0)&&l.push(`${a}s`),l.join(" ")}function cr(r,e){return U(r,{daemonRunning:e})}async function io(){let r=await P(),t=await new A().loadSchedules(),o=[],n;if(r.running&&r.pid){let s=lr(r.startTime),a=r.startTime?(0,Me.default)(r.startTime).format("YYYY-MM-DD HH:mm:ss"):"Unknown";n=[`${S.default.green("\u25CF")} ${S.default.green("active")} ${S.default.gray("(running)")}`,"",`${S.default.gray("Loaded:")} ${S.default.white(a)}`,`${S.default.gray("Active:")} ${S.default.green("active (running)")} since ${S.default.white(a)}`,`${S.default.gray("PID:")} ${S.default.white(r.pid.toString())}`,`${S.default.gray("Uptime:")} ${S.default.white(s)}`].join(`
73
+ `)}else n=[`${S.default.red("\u25CF")} ${S.default.red("inactive")} ${S.default.gray("(dead)")}`,"",`${S.default.gray("Loaded:")} ${S.default.gray("not found")}`,`${S.default.gray("Active:")} ${S.default.red("inactive (dead)")}`].join(`
74
+ `);let i=(0,st.default)(n,{title:S.default.bold("task-pipeliner-scheduler.service"),titleAlignment:"left",borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:1,bottom:0,left:0,right:0},borderColor:r.running?"green":"red"});if(o.push(i),t.length>0){let s=t.filter(l=>l.enabled).length,a=S.default.bold(`Schedules: ${s}/${t.length} enabled`);o.push(a);for(let l of t)o.push(cr(l,r.running))}else{let s=(0,st.default)(S.default.gray("No schedules configured"),{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"});o.push(s)}return`
75
+
76
+ ${o.join(`
77
+ `)}`}function ao(){process.stdout.write("\x1B[2J\x1B[H")}var ur=2,pr=24;function dr(){let r=typeof process.stdout.rows=="number"?process.stdout.rows:pr;return Math.max(5,r-ur)}function mr(r){let e=r.toString("utf8");return e==="\x1B[A"?"up":e==="\x1B[B"?"down":e==="\x1B[5~"?"pageup":e==="\x1B[6~"?"pagedown":e==="\x1B[H"||e==="\x1B[1~"?"home":e==="\x1B[4~"||e==="\x1B[F"?"end":null}async function lo(r){if(r){let e=process.stdin.isTTY&&process.stdout.isTTY,t=dr(),o=!0,n=[],i="",s=0,a=()=>{let m=n.length,f=Math.max(0,m-t);s=Math.min(s,f);let h=n.slice(s,s+t).join(`
78
+ `),w=m>t?S.default.dim(` [${s+1}-${Math.min(s+t,m)}/${m}] \u2191/\u2193 PgUp/PgDn: scroll`):"";(0,he.default)(`${h}
79
+ ${i}${w}`)},l=()=>{o=!1,e&&process.stdin.isTTY&&(process.stdin.setRawMode(!1),process.stdin.pause()),he.default.done(),process.exit(0)};process.on("SIGINT",l),process.on("SIGTERM",l),e&&process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",m=>{let f=typeof m=="string"?Buffer.from(m,"utf8"):m;if(f.length===1&&f[0]===3){l();return}let p=mr(f);if(!p||n.length<=t){p&&a();return}let h=Math.max(0,n.length-t);switch(p){case"up":s=Math.max(0,s-1);break;case"down":s=Math.min(h,s+1);break;case"pageup":s=Math.max(0,s-t);break;case"pagedown":s=Math.min(h,s+t);break;case"home":s=0;break;case"end":s=h;break}a()}));let c=async()=>{try{let m=await io(),f=await P();if(i=f.running?S.default.gray(`
80
+ Ctrl+C: exit (daemon keeps running)`):S.default.gray(`
81
+ Tip: tp schedule start -d to start daemon. Ctrl+C: exit.`),n=m.split(`
82
+ `),e)a();else{let p=f.running?S.default.gray(`
83
+ Press Ctrl+C to exit (daemon keeps running in background)`):S.default.gray(`
84
+ Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit.`);(0,he.default)(`${m}${p}`)}}catch(m){he.default.done(),console.error("Error updating status:",m),process.exit(1)}},d=setInterval(async()=>{if(!o){clearInterval(d);return}await c()},1e3);ao(),await c(),await new Promise(()=>{})}else{ao();let e=await io(),o=(await P()).running?"":S.default.gray(`
73
85
  Tip: To start the daemon, run: tp schedule start -d`);console.log(`${e}${o}
74
- `)}}async function Io(){let r=new j,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(h=>({id:h.id,label:Ht(h,"color")})),s=(await new I(!0).prompt("Select schedule to toggle:",t)).id,i=e.find(h=>h.id===s);if(!i){console.log("\u2717 Schedule not found");return}let a=!i.enabled;await r.toggleSchedule(s,a);let l=await $(),c={...i,enabled:a},f=a?m.default.bold.green("ENABLED"):m.default.bold.gray("DISABLED"),g=a?m.default.dim(" (will run at the times shown below)"):m.default.dim(" (will not run until you enable it again)");console.log(`
75
- \u2713 Schedule is now ${f}${g}
76
- `),console.log(G(c,{daemonRunning:l.running,emphasizeState:!0}))}async function Mo(){let r=new j,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:t}=await Ce.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to remove all ${e.length} schedule(s)?`,default:!1}]);if(!t){console.log("Cancelled");return}await r.saveSchedules([]),console.log(`\u2713 Removed all ${e.length} schedule(s)`)}var de=(0,D.join)((0,zt.homedir)(),".pipeliner"),No=(0,Ut.promisify)(Vt.exec),U=new Yt.Command;U.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
86
+ `)}}function uo(){let r=new co.Command("schedule").description("Manage workflow schedules").action(async()=>{await nt()});return r.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON). If no file given, select from nearest tp/schedules directory.").action(async e=>{await eo(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await to()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await so()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await nt()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await oo(e.daemon??!1)}),r.command("stop").description("Stop the scheduler daemon").action(async()=>{await ro()}),r.command("status").description('View daemon and schedule status (does not start the daemon). In live mode, Ctrl+C only exits the status view; the daemon keeps running if it was started with "tp schedule start -d".').option("-n, --no-follow","Show status once and exit (no live refresh)").action(async e=>{let t=e.follow!==!1;await lo(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await no()}),r}var po=[{filename:"example-hello.yaml",content:`name: Hello World (with choose)
87
+
88
+ # Interactive choice: stored as variable and used in later steps
89
+ steps:
90
+ - run: 'echo "Hello from task-pipeliner"'
91
+ - choose:
92
+ message: "Select action:"
93
+ options:
94
+ - id: greet
95
+ label: "Greet"
96
+ - id: info
97
+ label: "Show info"
98
+ as: action
99
+ - run: 'echo "You chose: {{ action }}"'
100
+ - when:
101
+ var:
102
+ action: greet
103
+ run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
104
+ - when:
105
+ var:
106
+ action: info
107
+ run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
108
+ `},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
109
+
110
+ # Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
111
+ # With profile, choose/prompt are skipped and these variables are used.
112
+ profiles:
113
+ - name: Dev
114
+ var:
115
+ mode: dev
116
+ label: "dev-build"
117
+ - name: Prod
118
+ var:
119
+ mode: prod
120
+ label: "prod-build"
121
+
122
+ steps:
123
+ - run: 'echo "Build workflow started..."'
124
+ - choose:
125
+ message: "Select mode (or run with --profile Dev/Prod to skip):"
126
+ options:
127
+ - id: dev
128
+ label: "Development"
129
+ - id: prod
130
+ label: "Production"
131
+ as: mode
132
+ - run: 'echo "Mode: {{ mode }}"'
133
+ - prompt:
134
+ message: "Enter build label"
135
+ as: label
136
+ default: "default"
137
+ - run: 'echo "Label: {{ label }}"'
138
+ - when:
139
+ var:
140
+ mode: dev
141
+ run: 'echo "Dev-only step (e.g. npm run build:dev)"'
142
+ - when:
143
+ var:
144
+ mode: prod
145
+ run: 'echo "Prod-only step (e.g. npm run build)"'
146
+ - run: 'echo "Done. Replace run steps with real commands."'
147
+ `}],mo=[{filename:"example-daily.yaml",content:`schedules:
148
+ # Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
149
+ - name: Daily Hello
150
+ cron: "0 9 * * *"
151
+ workflow: ../workflows/example-hello.yaml
152
+ `},{filename:"example-hourly.yaml",content:`schedules:
153
+ # With profile: choose/prompt are skipped and profile vars used (good for cron)
154
+ - name: Hourly Build (Dev)
155
+ cron: "0 * * * *"
156
+ workflow: ../workflows/example-build.yaml
157
+ profile: Dev
158
+ - name: Nightly Build (Prod)
159
+ cron: "0 2 * * *"
160
+ workflow: ../workflows/example-build.yaml
161
+ profile: Prod
162
+ `}];var Ne=require("fs"),fo=require("fs/promises"),we=require("path"),ge=b(require("chalk"),1);async function ho(){let r=De();if(!r)return console.error(ge.default.red(`
163
+ \u2717 No tp directory found`)),null;let e=(0,we.join)(r,"workflows");if(!(0,Ne.existsSync)(e))return console.error(ge.default.red(`
164
+ \u2717 No workflows directory found at ${e}`)),null;try{let o=(await(0,fo.readdir)(e)).filter(a=>{let l=(0,we.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(o.length===0)return console.error(ge.default.red(`
165
+ \u2717 No workflow files found in tp/workflows`)),null;let n=await Promise.all(o.map(async a=>{let l=(0,we.join)(e,a);try{let c=ce(l),d=(0,Ne.readFileSync)(l,"utf-8"),f=c.parse(d).name??"Untitled";return{id:l,label:`${a} - ${f}`}}catch{return{id:l,label:a}}}));return(await new I(!0).prompt("Select a workflow to run",n))?.id??null}catch(t){let o=t instanceof Error?t.message:String(t);return console.error(ge.default.red(`
166
+ \u2717 Failed to read tp directory: ${o}`)),null}}function go(r){return r.split("/").pop()??r}var ye=(0,_.join)((0,yo.homedir)(),".pipeliner"),fr=(0,bo.promisify)(wo.exec),q=new So.Command;q.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
77
167
 
78
168
  Define workflows in YAML or JSON files with conditional execution, parallel tasks,
79
169
  interactive prompts, variable substitution, and cron-based scheduling.
@@ -129,7 +219,7 @@ Quick Start:
129
219
 
130
220
  Note: After upgrading to a new version, if you see compatibility issues (e.g. schedules or daemon), run "tp clean" to reset ~/.pipeliner data.
131
221
 
132
- `).version(jt()).addHelpText("after",`
222
+ `).version(qt()).addHelpText("after",`
133
223
  Examples:
134
224
  $ tp setup
135
225
  $ tp run workflow.yaml
@@ -150,7 +240,7 @@ Resources:
150
240
  \u{1F4DA} Documentation: https://task-pipeliner.racgoo.com/
151
241
  \u{1F3A8} Visual Generator: https://task-pipeliner-generator.racgoo.com/
152
242
 
153
- See README.md for complete DSL reference.`);U.command("run").description("Run a workflow from a YAML or JSON file").argument("[file]","Path to the workflow file (YAML or JSON, relative or absolute). If omitted, will select from workflows in the nearest tp/workflows directory.").option("-s, --silent","Run in silent mode (suppress console output)").option("-p, --profile <name>","Run in profile mode (use profile name)").addHelpText("after",`
243
+ See README.md for complete DSL reference.`);q.command("run").description("Run a workflow from a YAML or JSON file").argument("[file]","Path to the workflow file (YAML or JSON, relative or absolute). If omitted, will select from workflows in the nearest tp/workflows directory.").option("-s, --silent","Run in silent mode (suppress console output)").option("-p, --profile <name>","Run in profile mode (use profile name)").addHelpText("after",`
154
244
  Examples:
155
245
  $ tp run workflow.yaml
156
246
  $ tp run workflow.json
@@ -175,124 +265,40 @@ Workflow File Structure:
175
265
  \u2022 all/any/not: Combine conditions
176
266
 
177
267
  Supported formats: YAML (.yaml, .yml) and JSON (.json)
178
- See README.md for complete DSL documentation.`).action(async(r,e)=>{try{let t=r??await Oo()??null;t||(console.error(p.default.red(`
179
- \u2717 No workflow file found`)),process.exit(1)),e.silent&&Nt();let o=ue(t);console.log(p.default.blue(`Loading workflow from ${t}...`));let n=(0,O.readFileSync)(t,"utf-8"),s=o.parse(n);if(!s.steps||!Array.isArray(s.steps))throw new Error("Invalid workflow: steps array is required");let i;if(e.profile){let l=e.profile.trim();if(!s.profiles?.length)throw new Error(`Profile "${l}" requested but workflow has no "profiles" defined. Add a "profiles" section to your workflow file.`);let c=s.profiles.find(f=>f.name===l);if(!c){let f=s.profiles.map(g=>g.name).join(", ");throw new Error(`Profile "${l}" not found. Available profile(s): ${f}`)}i=c.var}s._lineNumbers=o.extractStepLineNumbers(n),s._fileName=Fo(t),s._filePath=(0,D.resolve)(t),console.log(p.default.green(`Starting workflow execution...
180
- `)),await new re().execute(s,i?{profileVars:i}:void 0),console.log(p.default.green(`
181
- \u2713 Workflow completed successfully`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(p.default.red(`
182
- \u2717 Workflow failed: ${o}`)),process.exit(1)}});U.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
268
+ See README.md for complete DSL documentation.`).action(async(r,e)=>{try{let t=r??await ho()??null;t||(console.error(g.default.red(`
269
+ \u2717 No workflow file found`)),process.exit(1)),e.silent&&Jt();let o=ce(t);console.log(g.default.blue(`Loading workflow from ${t}...`));let n=(0,Y.readFileSync)(t,"utf-8"),i=o.parse(n);if(!i.steps||!Array.isArray(i.steps))throw new Error("Invalid workflow: steps array is required");let s;if(e.profile){let l=e.profile.trim();if(!i.profiles?.length)throw new Error(`Profile "${l}" requested but workflow has no "profiles" defined. Add a "profiles" section to your workflow file.`);let c=i.profiles.find(d=>d.name===l);if(!c){let d=i.profiles.map(m=>m.name).join(", ");throw new Error(`Profile "${l}" not found. Available profile(s): ${d}`)}s=c.var}i._lineNumbers=o.extractStepLineNumbers(n),i._fileName=go(t),i._filePath=(0,_.resolve)(t),console.log(g.default.green(`Starting workflow execution...
270
+ `)),await new le().execute(i,s?{profileVars:s}:void 0),console.log(g.default.green(`
271
+ \u2713 Workflow completed successfully`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(g.default.red(`
272
+ \u2717 Workflow failed: ${o}`)),process.exit(1)}});q.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
183
273
  Examples:
184
274
  $ tp open generator
185
275
  $ tp open docs
186
276
 
187
277
  Targets:
188
278
  generator Open the visual workflow generator (https://task-pipeliner-generator.racgoo.com/)
189
- docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(async r=>{let t={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[r.toLowerCase()];t||(console.error(p.default.red(`
190
- \u2717 Invalid target: ${r}`)),console.log(p.default.yellow(`
191
- Valid targets:`)),console.log(p.default.yellow(" \u2022 generator - Open the visual workflow generator")),console.log(p.default.yellow(" \u2022 docs - Open the documentation site")),process.exit(1));try{let o=process.platform,n;o==="darwin"?n=`open "${t}"`:o==="win32"?n=`start "${t}"`:n=`xdg-open "${t}"`,await No(n),console.log(p.default.green(`
192
- \u2713 Opening ${r==="generator"?"generator":"documentation"} in browser...`)),console.log(p.default.blue(` ${t}`))}catch(o){let n=o instanceof Error?o.message:String(o);console.error(p.default.red(`
193
- \u2717 Failed to open browser: ${n}`)),console.log(p.default.yellow(`
194
- Please visit manually: ${t}`)),process.exit(1)}});U.addCommand(_t());var jo=[{filename:"example-hello.yaml",content:`name: Hello World (with choose)
195
-
196
- # Interactive choice: stored as variable and used in later steps
197
- steps:
198
- - run: 'echo "Hello from task-pipeliner"'
199
- - choose:
200
- message: "Select action:"
201
- options:
202
- - id: greet
203
- label: "Greet"
204
- - id: info
205
- label: "Show info"
206
- as: action
207
- - run: 'echo "You chose: {{ action }}"'
208
- - when:
209
- var:
210
- action: greet
211
- run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
212
- - when:
213
- var:
214
- action: info
215
- run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
216
- `},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
217
-
218
- # Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
219
- # With profile, choose/prompt are skipped and these variables are used.
220
- profiles:
221
- - name: Dev
222
- var:
223
- mode: dev
224
- label: "dev-build"
225
- - name: Prod
226
- var:
227
- mode: prod
228
- label: "prod-build"
229
-
230
- steps:
231
- - run: 'echo "Build workflow started..."'
232
- - choose:
233
- message: "Select mode (or run with --profile Dev/Prod to skip):"
234
- options:
235
- - id: dev
236
- label: "Development"
237
- - id: prod
238
- label: "Production"
239
- as: mode
240
- - run: 'echo "Mode: {{ mode }}"'
241
- - prompt:
242
- message: "Enter build label"
243
- as: label
244
- default: "default"
245
- - run: 'echo "Label: {{ label }}"'
246
- - when:
247
- var:
248
- mode: dev
249
- run: 'echo "Dev-only step (e.g. npm run build:dev)"'
250
- - when:
251
- var:
252
- mode: prod
253
- run: 'echo "Prod-only step (e.g. npm run build)"'
254
- - run: 'echo "Done. Replace run steps with real commands."'
255
- `}],Ao=[{filename:"example-daily.yaml",content:`schedules:
256
- # Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
257
- - name: Daily Hello
258
- cron: "0 9 * * *"
259
- workflow: ../workflows/example-hello.yaml
260
- `},{filename:"example-hourly.yaml",content:`schedules:
261
- # With profile: choose/prompt are skipped and profile vars used (good for cron)
262
- - name: Hourly Build (Dev)
263
- cron: "0 * * * *"
264
- workflow: ../workflows/example-build.yaml
265
- profile: Dev
266
- - name: Nightly Build (Prod)
267
- cron: "0 2 * * *"
268
- workflow: ../workflows/example-build.yaml
269
- profile: Prod
270
- `}];U.command("setup").description("Create tp directory with workflows and schedules folders and add 2 example files in each (echo-based dummies). Run from project root for easy initial setup.").action(async()=>{let r=process.cwd(),e=(0,D.join)(r,"tp"),t=(0,D.join)(e,"workflows"),o=(0,D.join)(e,"schedules");(0,O.existsSync)(e)?console.log(p.default.gray(`
271
- tp directory already exists at ${e}`)):(await(0,F.mkdir)(e,{recursive:!0}),console.log(p.default.green(`
272
- \u2713 Created ${e}`)));let n=async(i,a)=>{(0,O.existsSync)(i)?console.log(p.default.gray(` ${a} already exists`)):(await(0,F.mkdir)(i,{recursive:!0}),console.log(p.default.green(`\u2713 Created ${a}`)))};await n(t,"tp/workflows"),await n(o,"tp/schedules");let s=[];for(let{filename:i,content:a}of jo){let l=(0,D.join)(t,i);(0,O.existsSync)(l)?console.log(p.default.gray(` Skipped (exists): tp/workflows/${i}`)):(await(0,F.writeFile)(l,a,"utf-8"),s.push(`tp/workflows/${i}`))}for(let{filename:i,content:a}of Ao){let l=(0,D.join)(o,i);(0,O.existsSync)(l)?console.log(p.default.gray(` Skipped (exists): tp/schedules/${i}`)):(await(0,F.writeFile)(l,a,"utf-8"),s.push(`tp/schedules/${i}`))}s.length>0&&(console.log(p.default.green(`
273
- \u2713 Added ${s.length} example file(s):`)),s.forEach(i=>console.log(p.default.dim(` ${i}`)))),console.log(p.default.dim(`
274
- Next: tp run tp/workflows/example-hello.yaml | tp schedule add tp/schedules/example-daily.yaml | tp schedule list`)),console.log()});var Lo=U.command("history").description("Manage workflow execution history");Lo.action(async()=>{let r=new I,e=await r.prompt("Select an action",[{id:"show",label:"Show - View and select a history to view"},{id:"remove",label:"Remove - Delete a specific history file"},{id:"remove-all",label:"Remove All - Delete all history files"}]);e?.id||(console.error(p.default.red(`
275
- \u2717 Invalid choice`)),process.exit(1));let t=new oe;switch(e.id){case"show":{let o=await t.getHistoryNames();if(o.length===0){console.log(p.default.yellow(`
276
- \u26A0 No history found`));return}let n=await r.prompt("Select a history to view",o.map(s=>({id:s,label:s})));n?.id||(console.error(p.default.red(`
277
- \u2717 Invalid choice`)),process.exit(1));try{let s=await t.getHistory(n.id);Bo(s,n.id)}catch(s){let i=s instanceof Error?s.message:String(s);console.error(p.default.red(`
278
- \u2717 Failed to load history: ${i}`)),process.exit(1)}break}case"remove":{let o=await t.getHistoryNames();if(o.length===0){console.log(p.default.yellow(`
279
- \u26A0 No history found`));return}let n=await r.prompt("Select a history to remove",o.map(s=>({id:s,label:s})));n?.id||(console.error(p.default.red(`
280
- \u2717 Invalid choice`)),process.exit(1));try{await t.removeHistory(n.id),console.log(p.default.green(`
281
- \u2713 Removed history: ${n.id}`))}catch(s){let i=s instanceof Error?s.message:String(s);console.error(p.default.red(`
282
- \u2717 Failed to remove history: ${i}`)),process.exit(1)}break}case"remove-all":{if((await r.prompt("Are you sure you want to remove all histories?",[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
283
- \u2717 Cancelled`));return}try{await t.clearAllHistories(),console.log(p.default.green(`
284
- \u2713 All histories removed`))}catch(n){let s=n instanceof Error?n.message:String(n);console.error(p.default.red(`
285
- \u2717 Failed to remove histories: ${s}`)),process.exit(1)}break}default:console.error(p.default.red(`
286
- \u2717 Unknown action: ${e.id}`)),process.exit(1)}});async function Oo(){let r=$e();if(!r)return console.error(p.default.red(`
287
- \u2717 No tp directory found`)),null;let e=(0,D.join)(r,"workflows");if(!(0,O.existsSync)(e))return console.error(p.default.red(`
288
- \u2717 No workflows directory found at ${e}`)),null;try{let o=(await(0,F.readdir)(e)).filter(a=>{let l=(0,D.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(o.length===0)return console.error(p.default.red(`
289
- \u2717 No workflow files found in ${e}`)),null;let n=await Promise.all(o.map(async a=>{let l=(0,D.join)(e,a);try{let c=ue(l),f=(0,O.readFileSync)(l,"utf-8"),h=c.parse(f).name??"Untitled";return{id:l,label:`${a} - ${h}`}}catch{return{id:l,label:a}}}));return(await new I(!0).prompt("Select a workflow to run",n)).id}catch(t){let o=t instanceof Error?t.message:String(t);return console.error(p.default.red(`
290
- \u2717 Failed to read tp directory: ${o}`)),null}}function Fo(r){return r.split("/").pop()??r}function Bo(r,e){console.log();let t=r.records.reduce((c,f)=>c+f.duration,0),o=r.records.filter(c=>c.status==="success").length,n=r.records.filter(c=>c.status==="failure").length,s=(0,Jt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=Q(t),l=[p.default.bold("Workflow Execution History"),"",`${p.default.cyan("File:")} ${e}`,`${p.default.cyan("Started:")} ${s}`,`${p.default.cyan("Total Duration:")} ${a}`,`${p.default.cyan("Total Steps:")} ${r.records.length}`,`${p.default.green("\u2713 Successful:")} ${o}`,n>0?`${p.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
291
- `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"})),r.records.forEach((c,f)=>{Wo(c,f+1,r.records.length)}),console.log()}function Wo(r,e,t){let o=_o(r.step),n=Ho(r.step),s=r.status==="success"?p.default.green("\u2713"):p.default.red("\u2717"),i=r.status==="success"?p.default.green("Success"):p.default.red("Failed"),a=Q(r.duration),l=[`${s} ${p.default.bold(`Step ${e}/${t}`)} - ${p.default.cyan(o)}`,`${p.default.gray("Duration:")} ${a} | ${p.default.gray("Status:")} ${i}`,"",p.default.white(n)].join(`
292
- `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Vo(r.output)&&zo(r.output)}function _o(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Ho(r){return"run"in r?`Command: ${p.default.yellow(r.run)}`:"choose"in r?`Message: ${p.default.yellow(r.choose.message)}`:"prompt"in r?`Message: ${p.default.yellow(r.prompt.message)} | Variable: ${p.default.cyan(r.prompt.as)}`:"parallel"in r?`Parallel execution with ${r.parallel.length} branches`:"fail"in r?`Error: ${p.default.red(r.fail.message)}`:"Unknown step type"}function Vo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function zo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
293
- `);console.log(p.default.green(" Output:")),console.log(e)}if(r.stderr.length>0){let e=r.stderr.map(t=>p.default.gray(` ${t}`)).join(`
294
- `);console.log(p.default.red(" Errors:")),console.log(e)}}U.command("clean").description("Remove all data in ~/.pipeliner (schedules, daemon state, workflow history). Use after upgrades if data is incompatible.").action(async()=>{if((await new I().prompt(`This will remove all data in ${p.default.yellow(de)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
295
- \u2717 Cancelled`));return}try{if(await H()){let t=await $();console.log(p.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new z().stopDaemon(),console.log(p.default.gray(" Daemon stopped"))}(0,O.existsSync)(de)?(await(0,F.rm)(de,{recursive:!0}),console.log(p.default.green(`
296
- \u2713 Removed ${de}`))):console.log(p.default.gray(`
297
- ${de} does not exist (already clean)`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(p.default.red(`
298
- \u2717 Clean failed: ${o}`)),process.exit(1)}});U.parse();
279
+ docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(async r=>{let t={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[r.toLowerCase()];t||(console.error(g.default.red(`
280
+ \u2717 Invalid target: ${r}`)),console.log(g.default.yellow(`
281
+ Valid targets:`)),console.log(g.default.yellow(" \u2022 generator - Open the visual workflow generator")),console.log(g.default.yellow(" \u2022 docs - Open the documentation site")),process.exit(1));try{let o=process.platform,n;o==="darwin"?n=`open "${t}"`:o==="win32"?n=`start "${t}"`:n=`xdg-open "${t}"`,await fr(n),console.log(g.default.green(`
282
+ \u2713 Opening ${r==="generator"?"generator":"documentation"} in browser...`)),console.log(g.default.blue(` ${t}`))}catch(o){let n=o instanceof Error?o.message:String(o);console.error(g.default.red(`
283
+ \u2717 Failed to open browser: ${n}`)),console.log(g.default.yellow(`
284
+ Please visit manually: ${t}`)),process.exit(1)}});q.addCommand(uo());q.command("setup").description("Create tp directory with workflows and schedules folders and add 2 example files in each (echo-based dummies). Run from project root for easy initial setup.").action(async()=>{let r=process.cwd(),e=(0,_.join)(r,"tp"),t=(0,_.join)(e,"workflows"),o=(0,_.join)(e,"schedules");(0,Y.existsSync)(e)?console.log(g.default.gray(`
285
+ tp directory already exists at ${e}`)):(await(0,J.mkdir)(e,{recursive:!0}),console.log(g.default.green(`
286
+ \u2713 Created ${e}`)));let n=async(s,a)=>{(0,Y.existsSync)(s)?console.log(g.default.gray(` ${a} already exists`)):(await(0,J.mkdir)(s,{recursive:!0}),console.log(g.default.green(`\u2713 Created ${a}`)))};await n(t,"tp/workflows"),await n(o,"tp/schedules");let i=[];for(let{filename:s,content:a}of po){let l=(0,_.join)(t,s);(0,Y.existsSync)(l)?console.log(g.default.gray(` Skipped (exists): tp/workflows/${s}`)):(await(0,J.writeFile)(l,a,"utf-8"),i.push(`tp/workflows/${s}`))}for(let{filename:s,content:a}of mo){let l=(0,_.join)(o,s);(0,Y.existsSync)(l)?console.log(g.default.gray(` Skipped (exists): tp/schedules/${s}`)):(await(0,J.writeFile)(l,a,"utf-8"),i.push(`tp/schedules/${s}`))}i.length>0&&(console.log(g.default.green(`
287
+ \u2713 Added ${i.length} example file(s):`)),i.forEach(s=>console.log(g.default.dim(` ${s}`)))),console.log(g.default.dim(`
288
+ Next: tp run tp/workflows/example-hello.yaml | tp schedule add tp/schedules/example-daily.yaml | tp schedule list`)),console.log()});var hr=q.command("history").description("Manage workflow execution history");hr.action(async()=>{let r=new I,e=new I(!0),t=await r.prompt("Select an action",[{id:"show",label:"Show - View and select a history to view"},{id:"remove",label:"Remove - Delete a specific history file"},{id:"remove-all",label:"Remove All - Delete all history files"}]);t?.id||(console.error(g.default.red(`
289
+ \u2717 Invalid choice`)),process.exit(1));let o=new ae;switch(t.id){case"show":{let n=await o.getHistoryNames();if(n.length===0){console.log(g.default.yellow(`
290
+ \u26A0 No history found`));return}let i=await e.prompt("Select a history to view",n.map(s=>({id:s,label:s})));i?.id||(console.error(g.default.red(`
291
+ \u2717 Invalid choice`)),process.exit(1));try{let s=await o.getHistory(i.id);Ot(s,i.id)}catch(s){let a=s instanceof Error?s.message:String(s);console.error(g.default.red(`
292
+ \u2717 Failed to load history: ${a}`)),process.exit(1)}break}case"remove":{let n=await o.getHistoryNames();if(n.length===0){console.log(g.default.yellow(`
293
+ \u26A0 No history found`));return}let i=await e.prompt("Select a history to remove",n.map(s=>({id:s,label:s})));i?.id||(console.error(g.default.red(`
294
+ \u2717 Invalid choice`)),process.exit(1));try{await o.removeHistory(i.id),console.log(g.default.green(`
295
+ \u2713 Removed history: ${i.id}`))}catch(s){let a=s instanceof Error?s.message:String(s);console.error(g.default.red(`
296
+ \u2717 Failed to remove history: ${a}`)),process.exit(1)}break}case"remove-all":{if((await r.prompt("Are you sure you want to remove all histories?",[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(g.default.yellow(`
297
+ \u2717 Cancelled`));return}try{await o.clearAllHistories(),console.log(g.default.green(`
298
+ \u2713 All histories removed`))}catch(i){let s=i instanceof Error?i.message:String(i);console.error(g.default.red(`
299
+ \u2717 Failed to remove histories: ${s}`)),process.exit(1)}break}default:console.error(g.default.red(`
300
+ \u2717 Unknown action: ${t.id}`)),process.exit(1)}});q.command("clean").description("Remove all data in ~/.pipeliner (schedules, daemon state, workflow history). Use after upgrades if data is incompatible.").action(async()=>{if((await new I().prompt(`This will remove all data in ${g.default.yellow(ye)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(g.default.yellow(`
301
+ \u2717 Cancelled`));return}try{if(await W()){let t=await P();console.log(g.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new z().stopDaemon(),console.log(g.default.gray(" Daemon stopped"))}(0,Y.existsSync)(ye)?(await(0,J.rm)(ye,{recursive:!0}),console.log(g.default.green(`
302
+ \u2713 Removed ${ye}`))):console.log(g.default.gray(`
303
+ ${ye} does not exist (already clean)`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(g.default.red(`
304
+ \u2717 Clean failed: ${o}`)),process.exit(1)}});q.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeliner",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "A task pipeline runner with condition-based workflow execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",