task-pipeliner 0.3.0 → 0.3.2

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
@@ -1,15 +1,15 @@
1
1
  # task-pipeliner
2
2
 
3
- > 조건 기반 작업 파이프라인 실행기로 아름다운 CLI 출력을 제공합니다
3
+ > 조건 기반 실행과 아름다운 CLI 출력을 제공하는 강력한 워크플로우 오케스트레이션 도구
4
4
 
5
- **버전:** 0.3.0
5
+ **버전:** 0.3.2
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/task-pipeliner)](https://www.npmjs.com/package/task-pipeliner)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
11
 
12
- **task-pipeliner**는 간단한 YAML 또는 JSON 파일로 복잡한 작업 파이프라인을 정의할 수 있는 현대적인 워크플로우 자동화 도구입니다. 조건부 실행, 병렬 작업, 대화형 프롬프트, 그리고 아름다운 터미널 출력을 제공하여 빌드 스크립트, 배포 워크플로우, CI/CD 파이프라인에 완벽합니다.
12
+ **task-pipeliner**는 간단한 YAML 또는 JSON 파일로 복잡한 워크플로우를 정의, 조율, 실행할 수 있는 현대적인 워크플로우 오케스트레이션 도구입니다. 조건부 실행, 병렬 작업, 대화형 프롬프트, 그리고 아름다운 터미널 출력을 제공하여 빌드 스크립트, 배포 워크플로우, CI/CD 파이프라인에 완벽합니다.
13
13
 
14
14
  **README-Language-Map** [KR [한국어 버전]](https://github.com/racgoo/task-pipeliner/blob/main/README.ko.md) / [EN [English Version]](https://github.com/racgoo/task-pipeliner)
15
15
 
@@ -447,13 +447,13 @@ steps: # 필수: 실행할 단계 배열
447
447
  - run: <command>
448
448
  when?: <condition> # 선택: 조건이 충족될 때만 실행
449
449
  timeout?: <number> # 선택: 타임아웃 (초 단위)
450
- retry?: <number> # 선택: 실패 시 재시도 횟수 (기본값: 0)
450
+ retry?: <number> | "Infinity" # 선택: 실패 시 재시도 횟수 (기본값: 0). "Infinity"로 무한 재시도 가능
451
451
  shell?: <array> # 선택: 쉘 설정 (workflow.shell 오버라이드)
452
452
  continue?: <bool> # 선택: 이 스텝 이후 다음 스텝으로 진행할지 여부 (성공/실패 무관)
453
453
  onError?: # 선택: 에러 처리 동작
454
454
  run: <command> # 메인 run 명령이 실패했을 때 실행할 대체 명령 (사이드 이펙트)
455
455
  timeout?: <number> # 선택: 이 fallback 명령의 타임아웃
456
- retry?: <number> # 선택: 이 fallback 명령의 재시도 횟수
456
+ retry?: <number> | "Infinity" # 선택: 이 fallback 명령의 재시도 횟수. "Infinity"로 무한 재시도 가능
457
457
  onError?: ... # 선택: 중첩 fallback (재귀 onError 체인)
458
458
  ```
459
459
 
@@ -461,7 +461,7 @@ steps: # 필수: 실행할 단계 배열
461
461
  - `run` (필수): `string` - 실행할 셸 명령
462
462
  - `when` (선택): `Condition` - 실행 전 확인할 조건
463
463
  - `timeout` (선택): `number` - 최대 실행 시간 (초 단위). 이 시간을 초과하면 명령이 종료됩니다.
464
- - `retry` (선택): `number` - 실패 시 재시도 횟수 (기본값: 0, 재시도 없음)
464
+ - `retry` (선택): `number | "Infinity"` - 실패 시 재시도 횟수 (기본값: 0, 재시도 없음). `"Infinity"`로 성공할 때까지 무한 재시도 가능
465
465
  - `shell` (선택): `string`의 `array` - 이 스텝의 쉘 설정. 워크플로우의 전역 `shell`을 오버라이드합니다. 형식: `[프로그램, ...인자]`. 예: `[bash, -lc]`, `[zsh, -c]`.
466
466
  - `continue` (선택): `boolean` - 이 스텝 완료 후 다음 스텝으로 진행할지 여부를 제어합니다 (성공/실패와 무관).
467
467
  - `continue: true` - 항상 다음 스텝으로 진행 (이 스텝이 실패해도)
@@ -469,7 +469,7 @@ steps: # 필수: 실행할 단계 배열
469
469
  - `continue` 미설정 (기본값) - 성공 시 진행, 실패 시 중단
470
470
  - `onError.run` (선택): `string` - 메인 `run` 명령이 (자신의 재시도 후에도) 실패했을 때 실행할 대체 명령. **onError는 단순히 사이드 이펙트(예: 정리 작업, 롤백)를 수행하며, 스텝의 성공/실패 여부에는 영향을 주지 않습니다.** 메인 `run`이 실패하면 이 스텝은 실패로 간주됩니다.
471
471
  - `onError.timeout` (선택): `number` - 이 fallback 명령의 타임아웃.
472
- - `onError.retry` (선택): `number` - 이 fallback 명령의 재시도 횟수.
472
+ - `onError.retry` (선택): `number | "Infinity"` - 이 fallback 명령의 재시도 횟수. `"Infinity"`로 무한 재시도 가능.
473
473
 
474
474
  **예제:**
475
475
  ```yaml
@@ -505,6 +505,14 @@ steps:
505
505
  - run: npm install
506
506
  retry: 3
507
507
 
508
+ # 무한 재시도 명령 (성공할 때까지 재시도)
509
+ - run: npm install
510
+ retry: Infinity
511
+
512
+ # PM2처럼 프로세스 관리: 서버가 죽으면 자동 재시작
513
+ - run: node server.js
514
+ retry: Infinity
515
+
508
516
  # 타임아웃과 재시도 모두 사용
509
517
  - run: npm install
510
518
  timeout: 60
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # task-pipeliner
2
2
 
3
- > A powerful, condition-based task pipeline runner with beautiful CLI output
3
+ > A powerful workflow orchestration tool with condition-based execution and beautiful CLI output
4
4
 
5
- **Version:** 0.3.0
5
+ **Version:** 0.3.2
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/task-pipeliner)](https://www.npmjs.com/package/task-pipeliner)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
11
 
12
- **task-pipeliner** is a modern workflow automation tool that lets you define complex task pipelines using simple YAML or JSON files. With conditional execution, parallel tasks, interactive prompts, and beautiful terminal output, it's perfect for build scripts, deployment workflows, and CI/CD pipelines.
12
+ **task-pipeliner** is a modern workflow orchestration tool that lets you define, coordinate, and execute complex workflows using simple YAML or JSON files. With conditional execution, parallel tasks, interactive prompts, and beautiful terminal output, it's perfect for build scripts, deployment workflows, and CI/CD pipelines.
13
13
 
14
14
  **README-Language-Map** [KR [한국어 버전]](https://github.com/racgoo/task-pipeliner/blob/main/README.ko.md) / [EN [English Version]](https://github.com/racgoo/task-pipeliner)
15
15
 
@@ -447,13 +447,13 @@ Execute a shell command.
447
447
  - run: <command>
448
448
  when?: <condition> # Optional: Execute only if condition is met
449
449
  timeout?: <number> # Optional: Timeout in seconds
450
- retry?: <number> # Optional: Number of retries on failure (default: 0)
450
+ retry?: <number> | "Infinity" # Optional: Number of retries on failure (default: 0). Use "Infinity" for infinite retries
451
451
  shell?: <array> # Optional: Shell configuration (overrides workflow.shell)
452
452
  continue?: <bool> # Optional: Continue to next step after this step completes (regardless of success/failure)
453
453
  onError?: # Optional: Error handling behavior
454
454
  run: <command> # Fallback command when main run command fails (side effect)
455
455
  timeout?: <number> # Optional: Timeout for this fallback command
456
- retry?: <number> # Optional: Retry count for this fallback command
456
+ retry?: <number> | "Infinity" # Optional: Retry count for this fallback command. Use "Infinity" for infinite retries
457
457
  onError?: ... # Optional: Nested fallback (recursive onError chain)
458
458
  ```
459
459
 
@@ -461,7 +461,7 @@ Execute a shell command.
461
461
  - `run` (required): `string` - Shell command to execute
462
462
  - `when` (optional): `Condition` - Condition to check before execution
463
463
  - `timeout` (optional): `number` - Maximum execution time in seconds. Command will be killed if it exceeds this time.
464
- - `retry` (optional): `number` - Number of retry attempts if command fails (default: 0, meaning no retry)
464
+ - `retry` (optional): `number | "Infinity"` - Number of retry attempts if command fails (default: 0, meaning no retry). Use `"Infinity"` for infinite retries until success
465
465
  - `shell` (optional): `array` of `string` - Shell configuration for this step. Overrides workflow's global `shell`. Format: `[program, ...args]`. Example: `[bash, -lc]`, `[zsh, -c]`.
466
466
  - `continue` (optional): `boolean` - Controls whether to proceed to the next step after this step completes, regardless of success or failure.
467
467
  - `continue: true` - Always proceed to the next step (even if this step fails)
@@ -469,7 +469,7 @@ Execute a shell command.
469
469
  - `continue` not set (default) - Proceed on success, stop on failure
470
470
  - `onError.run` (optional): `string` - Fallback command executed when the main `run` command (after its retries) fails. **onError only performs side effects (e.g., cleanup, rollback) and does not affect the step's success/failure status.** If the main `run` fails, this step is considered failed regardless of onError execution.
471
471
  - `onError.timeout` (optional): `number` - Timeout for this fallback command.
472
- - `onError.retry` (optional): `number` - Retry count for this fallback command.
472
+ - `onError.retry` (optional): `number | "Infinity"` - Retry count for this fallback command. Use `"Infinity"` for infinite retries.
473
473
 
474
474
  **Examples:**
475
475
  ```yaml
@@ -505,6 +505,14 @@ steps:
505
505
  - run: npm install
506
506
  retry: 3
507
507
 
508
+ # Command with infinite retry (retry until success)
509
+ - run: npm install
510
+ retry: Infinity
511
+
512
+ # PM2-like process manager: auto-restart crashed server
513
+ - run: node server.js
514
+ retry: Infinity
515
+
508
516
  # Using both timeout and retry
509
517
  - run: npm install
510
518
  timeout: 60
package/dist/index.cjs CHANGED
@@ -1,27 +1,27 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Ut=Object.create;var De=Object.defineProperty;var Jt=Object.getOwnPropertyDescriptor;var qt=Object.getOwnPropertyNames;var Gt=Object.getPrototypeOf,Zt=Object.prototype.hasOwnProperty;var Xt=(r,e)=>()=>(r&&(e=r(r=0)),e);var Kt=(r,e)=>{for(var t in e)De(r,t,{get:e[t],enumerable:!0})},Qt=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of qt(e))!Zt.call(r,n)&&n!==t&&De(r,n,{get:()=>e[n],enumerable:!(o=Jt(e,n))||o.enumerable});return r};var y=(r,e,t)=>(t=r!=null?Ut(Gt(r)):{},Qt(e||!r||!r.__esModule?De(t,"default",{value:r,enumerable:!0}):t,r));var et={};Kt(et,{DAEMON_DIR:()=>q,getDaemonErrorLogPath:()=>Me,getDaemonPid:()=>Te,getDaemonStartTime:()=>Qe,getDaemonStatus:()=>$,isDaemonRunning:()=>A,readDaemonErrorLog:()=>je,removeDaemonPid:()=>se,saveDaemonPid:()=>to,writeDaemonError:()=>Ie});function eo(r){try{return process.kill(r,0),!0}catch{return!1}}async function Te(){try{if(!(0,V.existsSync)(N))return null;let r=await(0,x.readFile)(N,"utf-8"),e=parseInt(r.trim(),10);return isNaN(e)?(await(0,x.unlink)(N),null):eo(e)?e:(await(0,x.unlink)(N),null)}catch(r){if(r instanceof Error&&"code"in r&&r.code==="ENOENT")return null;throw r}}async function A(){return await Te()!==null}async function to(){await(0,x.mkdir)(q,{recursive:!0}),await(0,x.writeFile)(N,process.pid.toString(),"utf-8");let r=new Date().toISOString();await(0,x.writeFile)(re,r,"utf-8")}async function Ie(r){try{await(0,x.mkdir)(q,{recursive:!0});let e=`${new Date().toISOString()} ${r.message}
3
- ${r.stack??""}
4
- `;await(0,x.writeFile)(de,e,"utf-8")}catch{}}async function se(){try{(0,V.existsSync)(N)&&await(0,x.unlink)(N),(0,V.existsSync)(re)&&await(0,x.unlink)(re)}catch{}}async function Qe(){try{if((0,V.existsSync)(re)){let e=(await(0,x.readFile)(re,"utf-8")).trim();if(e)return e}if((0,V.existsSync)(N)){let r=await(0,x.stat)(N);return new Date(r.mtime).toISOString()}return null}catch{return null}}function Me(){return de}async function je(){try{return(0,V.existsSync)(de)&&(await(0,x.readFile)(de,"utf-8")).trim()||null}catch{return null}}async function $(){let r=await Te(),e=r?await Qe():null;return{running:r!==null,pid:r,startTime:e}}var V,x,Ke,ne,q,N,re,de,ie=Xt(()=>{"use strict";V=require("fs"),x=require("fs/promises"),Ke=require("os"),ne=require("path"),q=(0,ne.join)((0,Ke.homedir)(),".pipeliner","daemon"),N=(0,ne.join)(q,"scheduler.pid"),re=(0,ne.join)(q,"scheduler.started");de=(0,ne.join)(q,"error.log")});var _t=require("child_process"),pe=require("fs"),Pe=require("fs/promises"),Vt=require("os"),U=require("path"),Ht=require("util"),Xe=y(require("boxen"),1),p=y(require("chalk"),1),zt=require("commander"),Yt=y(require("dayjs"),1);ie();var z=require("path"),ct=y(require("chalk"),1),be=y(require("log-update"),1);var ot=y(require("readline"),1),C=y(require("chalk"),1),Ne=y(require("inquirer"),1),tt=15,L=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,t){if(this.searchable)return this.promptWithSearch(e,t);let{choice:o}=await Ne.default.prompt([{type:"list",name:"choice",message:C.default.cyan(e),choices:t.map(s=>({name:s.label,value:s.id})),pageSize:tt}]),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=ot.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(C.default.cyan(`? ${e}`));let m=n?C.default.gray(` Filter: ${n}`)+C.default.gray(` (${i.length}/${t.length})`):C.default.gray(" Type to filter, \u2191\u2193 to navigate, Enter to select");console.log(m),console.log();let d=tt,w=0,v=i.length;if(i.length>d){let k=Math.floor(d/2);w=Math.max(0,s-k),v=Math.min(i.length,w+d),v===i.length&&(w=Math.max(0,v-d))}if(i.length===0)console.log(C.default.yellow(" No matches found"));else{w>0&&console.log(C.default.gray(` \u2191 ${w} more above`));for(let k=w;k<v;k++){let R=i[k];console.log(k===s?C.default.cyan(`\u276F ${R.label}`):C.default.white(` ${R.label}`))}v<i.length&&console.log(C.default.gray(` \u2193 ${i.length-v} more below`))}},c=()=>{let m=n.toLowerCase();i=m?t.filter(d=>d.label.toLowerCase().includes(m)):[...t],s>=i.length&&(s=Math.max(0,i.length-1))},f=m=>{let d=m.toString();if(d===""&&(g(),process.exit(0)),d==="\r"||d===`
5
- `){i.length>0&&(g(),o(i[s]));return}if(d==="\x1B"&&m.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)})}},fe=class{async prompt(e,t){let{value:o}=await Ne.default.prompt([{type:"input",name:"value",message:C.default.cyan(e),default:t}]);return o}};var me=y(require("boxen"),1),G=y(require("chalk"),1);function Ae(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,me.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 Z(r,e=!1,t){let o=r?"\u2713 Completed":"\u2717 Failed",n=r?G.default.green(o):G.default.red(o);if(t!==void 0){let s=X(t);return`${n} ${G.default.gray(`(${s})`)}`}return n}function ae(r){return(0,me.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 rt(r){return(0,me.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 nt(r){let e=r?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return r?G.default.green(e):G.default.red(e)}function Oe(r,e=!1){return`${e?"| \u2502 ":"\u2502 "}${r}`}function X(r){return`${(r/1e3).toFixed(3)}s`}var st=require("fs"),it=require("path"),K=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,it.resolve)(process.cwd(),t);return(0,st.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 D=require("fs/promises"),at=require("os"),H=require("path"),lt=y(require("dayjs"),1),Q=(0,H.join)((0,at.homedir)(),".pipeliner","workflow-history"),ee=class{constructor(){}async saveHistory(e){await(0,D.mkdir)(Q,{recursive:!0});let t=(0,lt.default)().format("YYYY-MM-DD_HH-mm-ss"),o=Math.random().toString(36).slice(2,6),n=(0,H.join)(Q,`workflow-${t}-${o}.json`);return await(0,D.writeFile)(n,JSON.stringify(e,null,2),{encoding:"utf8"}),n}async clearAllHistories(){await(0,D.rm)(Q,{recursive:!0,force:!0})}async removeHistory(e){await(0,D.rm)((0,H.join)(Q,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,D.readdir)(Q)).map(o=>(0,H.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,D.readFile)((0,H.join)(Q,e),{encoding:"utf8"});return JSON.parse(t)}};var he=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 ee,t={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(t)}getDuration(){return Date.now()-this.recordStartTimestamp}};var Fe=require("child_process");var ge=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="",m=null;o&&o>0&&(m=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:v,remaining:k}=this.processStreamBuffer(w,f);l.push(...v),f=k}),a.stderr?.on("data",d=>{let w=d.toString(),{lines:v,remaining:k}=this.processStreamBuffer(w,g);c.push(...v),g=k}),a.on("close",d=>{m&&clearTimeout(m),f.trim()&&l.push(f),g.trim()&&c.push(g),s({success:d===0,stdout:l,stderr:c})}),a.on("error",d=>{m&&clearTimeout(m);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=Ae(t,n,s,{borderColor:o?"green":"cyan"});console.log(f);let g=Date.now();return new Promise(m=>{let d=this.spawnWithShell(e,i,l),w="",v="",k=null;a&&a>0&&(k=setTimeout(()=>{d.kill("SIGTERM");let R=`Command timed out after ${a} seconds`,I=ae(R);console.error(I);let W=Date.now()-g,_=Z(!1,!1,W);console.log(_),m(!1)},a*1e3)),d.stdout?.on("data",R=>{let I=R.toString(),{lines:W,remaining:_}=this.processStreamBuffer(I,w);W.forEach(Ce=>process.stdout.write(`\u2502 ${Ce}
6
- `)),w=_}),d.stderr?.on("data",R=>{let I=R.toString(),{lines:W,remaining:_}=this.processStreamBuffer(I,v);W.forEach(Ce=>process.stderr.write(`\u2502 ${Ce}
7
- `)),v=_}),d.on("close",R=>{k&&clearTimeout(k),w.trim()&&process.stdout.write(`\u2502 ${w}
8
- `),v.trim()&&process.stderr.write(`\u2502 ${v}
9
- `);let I=R===0,W=Date.now()-g,_=Z(I,!1,W);console.log(_),m(I)}),d.on("error",R=>{k&&clearTimeout(k);let I=ae(`Error: ${R.message}`);console.error(I),m(!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(`
2
+ "use strict";var Yt=Object.create;var De=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var Jt=Object.getOwnPropertyNames;var qt=Object.getPrototypeOf,Gt=Object.prototype.hasOwnProperty;var Zt=(o,e)=>()=>(o&&(e=o(o=0)),e);var Xt=(o,e)=>{for(var t in e)De(o,t,{get:e[t],enumerable:!0})},Kt=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Jt(e))!Gt.call(o,n)&&n!==t&&De(o,n,{get:()=>e[n],enumerable:!(r=Ut(e,n))||r.enumerable});return o};var y=(o,e,t)=>(t=o!=null?Yt(qt(o)):{},Kt(e||!o||!o.__esModule?De(t,"default",{value:o,enumerable:!0}):t,o));var Qe={};Xt(Qe,{DAEMON_DIR:()=>q,getDaemonErrorLogPath:()=>Me,getDaemonPid:()=>Te,getDaemonStartTime:()=>Ke,getDaemonStatus:()=>R,isDaemonRunning:()=>A,readDaemonErrorLog:()=>je,removeDaemonPid:()=>se,saveDaemonPid:()=>er,writeDaemonError:()=>Ie});function Qt(o){try{return process.kill(o,0),!0}catch{return!1}}async function Te(){try{if(!(0,V.existsSync)(N))return null;let o=await(0,x.readFile)(N,"utf-8"),e=parseInt(o.trim(),10);return isNaN(e)?(await(0,x.unlink)(N),null):Qt(e)?e:(await(0,x.unlink)(N),null)}catch(o){if(o instanceof Error&&"code"in o&&o.code==="ENOENT")return null;throw o}}async function A(){return await Te()!==null}async function er(){await(0,x.mkdir)(q,{recursive:!0}),await(0,x.writeFile)(N,process.pid.toString(),"utf-8");let o=new Date().toISOString();await(0,x.writeFile)(oe,o,"utf-8")}async function Ie(o){try{await(0,x.mkdir)(q,{recursive:!0});let e=`${new Date().toISOString()} ${o.message}
3
+ ${o.stack??""}
4
+ `;await(0,x.writeFile)(fe,e,"utf-8")}catch{}}async function se(){try{(0,V.existsSync)(N)&&await(0,x.unlink)(N),(0,V.existsSync)(oe)&&await(0,x.unlink)(oe)}catch{}}async function Ke(){try{if((0,V.existsSync)(oe)){let e=(await(0,x.readFile)(oe,"utf-8")).trim();if(e)return e}if((0,V.existsSync)(N)){let o=await(0,x.stat)(N);return new Date(o.mtime).toISOString()}return null}catch{return null}}function Me(){return fe}async function je(){try{return(0,V.existsSync)(fe)&&(await(0,x.readFile)(fe,"utf-8")).trim()||null}catch{return null}}async function R(){let o=await Te(),e=o?await Ke():null;return{running:o!==null,pid:o,startTime:e}}var V,x,Xe,ne,q,N,oe,fe,ie=Zt(()=>{"use strict";V=require("fs"),x=require("fs/promises"),Xe=require("os"),ne=require("path"),q=(0,ne.join)((0,Xe.homedir)(),".pipeliner","daemon"),N=(0,ne.join)(q,"scheduler.pid"),oe=(0,ne.join)(q,"scheduler.started");fe=(0,ne.join)(q,"error.log")});var Wt=require("child_process"),de=require("fs"),Pe=require("fs/promises"),_t=require("os"),U=require("path"),Vt=require("util"),Ze=y(require("boxen"),1),p=y(require("chalk"),1),Ht=require("commander"),zt=y(require("dayjs"),1);ie();var z=require("path"),lt=y(require("chalk"),1),Se=y(require("log-update"),1);var tt=y(require("readline"),1),D=y(require("chalk"),1),Ne=y(require("inquirer"),1),et=15,L=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,t){if(this.searchable)return this.promptWithSearch(e,t);let{choice:r}=await Ne.default.prompt([{type:"list",name:"choice",message:D.default.cyan(e),choices:t.map(s=>({name:s.label,value:s.id})),pageSize:et}]),n=t.find(s=>s.id===r);if(!n)throw new Error(`Invalid choice: ${r}`);return n}async promptWithSearch(e,t){return new Promise(r=>{let n="",s=0,i=[...t],a=tt.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(D.default.cyan(`? ${e}`));let h=n?D.default.gray(` Filter: ${n}`)+D.default.gray(` (${i.length}/${t.length})`):D.default.gray(" Type to filter, \u2191\u2193 to navigate, Enter to select");console.log(h),console.log();let d=et,w=0,S=i.length;if(i.length>d){let v=Math.floor(d/2);w=Math.max(0,s-v),S=Math.min(i.length,w+d),S===i.length&&(w=Math.max(0,S-d))}if(i.length===0)console.log(D.default.yellow(" No matches found"));else{w>0&&console.log(D.default.gray(` \u2191 ${w} more above`));for(let v=w;v<S;v++){let $=i[v];console.log(v===s?D.default.cyan(`\u276F ${$.label}`):D.default.white(` ${$.label}`))}S<i.length&&console.log(D.default.gray(` \u2193 ${i.length-S} 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(),r(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:r}=await Ne.default.prompt([{type:"input",name:"value",message:D.default.cyan(e),default:t}]);return r}};var he=y(require("boxen"),1),G=y(require("chalk"),1);function Ae(o,e,t,r={}){let{borderColor:n="cyan",isNested:s=!1}=r,i;e!==void 0&&(t?i=`line ${e} in ${t}`:i=`line ${e}`);let a=s?`\u2502 ${o}`:`> ${o}`;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 Z(o,e=!1,t){let r=o?"\u2713 Completed":"\u2717 Failed",n=o?G.default.green(r):G.default.red(r);if(t!==void 0){let s=X(t);return`${n} ${G.default.gray(`(${s})`)}`}return n}function ae(o){return(0,he.default)(`\u2717 ${o}`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"red"})}function rt(o){return(0,he.default)(`> Starting parallel execution (${o} branches)`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"yellow"})}function ot(o){let e=o?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return o?G.default.green(e):G.default.red(e)}function Oe(o,e=!1){return`${e?"| \u2502 ":"\u2502 "}${o}`}function X(o){return`${(o/1e3).toFixed(3)}s`}var nt=require("fs"),st=require("path"),K=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[r,n]of Object.entries(e.var)){let s=this.workspace.getVariable(r),i=this.workspace.getFact(r),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(),r=(0,st.resolve)(process.cwd(),t);return(0,nt.existsSync)(r)}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 T=require("fs/promises"),it=require("os"),H=require("path"),at=y(require("dayjs"),1),Q=(0,H.join)((0,it.homedir)(),".pipeliner","workflow-history"),ee=class{constructor(){}async saveHistory(e){await(0,T.mkdir)(Q,{recursive:!0});let t=(0,at.default)().format("YYYY-MM-DD_HH-mm-ss"),r=Math.random().toString(36).slice(2,6),n=(0,H.join)(Q,`workflow-${t}-${r}.json`);return await(0,T.writeFile)(n,JSON.stringify(e,null,2),{encoding:"utf8"}),n}async clearAllHistories(){await(0,T.rm)(Q,{recursive:!0,force:!0})}async removeHistory(e){await(0,T.rm)((0,H.join)(Q,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,T.readdir)(Q)).map(r=>(0,H.basename)(r));return t.sort((r,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(r),a=s(n);return i===a?n.localeCompare(r):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,T.readFile)((0,H.join)(Q,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,r,n){let s=this.getDuration();return this.records.push({step:e,context:t,output:r,duration:s,status:n}),s}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new ee,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,r,n,s=!1,i=!1,a,l,c,f,g){return s?this.runBuffered(e,c,f,g):this.runRealtime(e,r||e,i,a,l,c,f,g)}async runBuffered(e,t,r,n){return new Promise((s,i)=>{let a=this.spawnWithShell(e,t,n),l=[],c=[],f="",g="",h=null;r&&r>0&&(h=setTimeout(()=>{a.kill("SIGTERM");let d=`Command timed out after ${r} seconds`;c.push(d),s({success:!1,stdout:l,stderr:c})},r*1e3)),a.stdout?.on("data",d=>{let w=d.toString(),{lines:S,remaining:v}=this.processStreamBuffer(w,f);l.push(...S),f=v}),a.stderr?.on("data",d=>{let w=d.toString(),{lines:S,remaining:v}=this.processStreamBuffer(w,g);c.push(...S),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,r,n,s,i,a,l){let f=Ae(t,n,s,{borderColor:r?"green":"cyan"});console.log(f);let g=Date.now();return new Promise(h=>{let d=this.spawnWithShell(e,i,l),w="",S="",v=null;a&&a>0&&(v=setTimeout(()=>{d.kill("SIGTERM");let $=`Command timed out after ${a} seconds`,C=ae($);console.error(C);let W=Date.now()-g,_=Z(!1,!1,W);console.log(_),h(!1)},a*1e3)),d.stdout?.on("data",$=>{let C=$.toString(),{lines:W,remaining:_}=this.processStreamBuffer(C,w);W.forEach(Ce=>process.stdout.write(`\u2502 ${Ce}
6
+ `)),w=_}),d.stderr?.on("data",$=>{let C=$.toString(),{lines:W,remaining:_}=this.processStreamBuffer(C,S);W.forEach(Ce=>process.stderr.write(`\u2502 ${Ce}
7
+ `)),S=_}),d.on("close",$=>{v&&clearTimeout(v),w.trim()&&process.stdout.write(`\u2502 ${w}
8
+ `),S.trim()&&process.stderr.write(`\u2502 ${S}
9
+ `);let C=$===0,W=Date.now()-g,_=Z(C,!1,W);console.log(_),h(C)}),d.on("error",$=>{v&&clearTimeout(v);let C=ae(`Error: ${$.message}`);console.error(C),h(!1)})})}createSpawnOptions(e){let t={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(t.cwd=e),t}spawnWithShell(e,t,r){if(r&&r.length>0){let n=r[0],s=[...r.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 r=t+e,n=[],s=r;for(;s.includes(`
10
10
  `);){let i=s.indexOf(`
11
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=Ae(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=Z(e.success,o);console.log(a)}};function oo(r,e,t){if(e.hasVariable(r)){let o=e.getVariable(r);return o??t}if(e.hasFact(r)){let o=e.getFact(r);return typeof o=="string"?o:String(o)}if(e.hasChoice(r)){let o=e.getChoice(r);return o??t}return t}function we(r,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return r.replace(t,(o,n)=>oo(n,e,o))}var ye=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 te=class r{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new ye,this.taskRunner=new ge,this.choicePrompt=new L,this.textPrompt=new fe}resolveBaseDir(e){if(e.baseDir)if((0,z.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,z.dirname)(e._filePath);this.baseDir=(0,z.resolve)(t,e.baseDir)}else this.baseDir=(0,z.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 K(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 he,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=X(s);console.log(ct.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=Z(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=we(e.run,this.workspace),a=e.shell||this.globalShell,l=e.retry??0,c=e.timeout,f=!1,g=0;for(;g<=l;){let m=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,c,a),d=typeof m=="boolean"?m:m.success;if(f=m,d||g>=l)break;if(g++,g<=l){let w=Math.min(1e3*Math.pow(2,g-1),1e4);await new Promise(v=>setTimeout(v,w))}}return f}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=we(e.prompt.message,this.workspace),s=e.prompt.default?we(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 K(g.workspace).evaluate(f.when))continue;let m=this.getBranchDisplayName(f,c);o.push({index:c,name:m,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],m=t[f];c.status="running";try{let d=await this.executeStep(g,m,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:m}}catch(d){m.workspace.setStepResult(m.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:m}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),be.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,be.default)(n.join(`
16
- `)):(0,be.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 m=`Branch ${l+1} failed: ${f instanceof Error?f.message:String(f)}`,d=ae(m);console.error(d)}else if(c&&typeof c=="object"&&"stdout"in c){let m=c;if(n=n&&m.success,m.stdout.length>0||m.stderr.length>0||!m.success){let d=t[l],w=this.getBranchDisplayName(d,l);this.taskRunner.displayBufferedOutput(m,w,!1,g.lineNumber,g.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let i=nt(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 K(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=rt(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 mt=require("yaml"),_e=require("zod");var u=require("zod"),ro=u.z.object({file:u.z.string()}),no=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()}),so=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),io=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),ao=u.z.object({choice:u.z.string()}),lo=u.z.union([ro,ao,no,so,io]),M=u.z.lazy(()=>u.z.union([lo,u.z.object({all:u.z.array(M)}),u.z.object({any:u.z.array(M)}),u.z.object({not:M})])),ut=u.z.lazy(()=>u.z.object({run:u.z.string(),timeout:u.z.number().optional(),retry:u.z.number().optional(),onError:ut.optional()})),pt=u.z.object({run:u.z.string(),when:M.optional(),timeout:u.z.number().optional(),retry:u.z.number().optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),continue:u.z.boolean().optional(),onError:ut.optional()}),co=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:M.optional()}),uo=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:M.optional()});function dt(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=dt(t);if(o.found)return o}return{found:!1}}var ft=u.z.lazy(()=>u.z.union([pt,u.z.object({parallel:u.z.array(u.z.lazy(()=>ft)),when:M.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:M.optional()})]).superRefine((r,e)=>{let t=dt(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)`})})),po=u.z.lazy(()=>u.z.union([pt,co,uo,u.z.object({parallel:u.z.array(ft),when:M.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:M.optional()})])),fo=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))}),mo=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(fo).optional(),steps:u.z.array(po).min(1,"Workflow must have at least one step")});function Le(r){return mo.parse(r)}function ht(r,e){let t=r.path;if(r.code==="custom"){let n=Be(t);return` - ${r.message}${n}`}if(r.message==="Invalid input"){let n=Be(t),s=ho(t,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let o=Be(t);return` - ${r.message}${o}`}function Be(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 b(r,e,t){let o=t?`
12
+ `).forEach(r=>{r.trim()&&console.log(`| ${r}`)}):console.log(e)}displayBufferedOutput(e,t,r=!1,n,s){let i=Ae(t,n,s,{borderColor:"cyan",isNested:r});this.formatNestedOutput(i,r),e.stdout.forEach(l=>{let c=Oe(l,r);process.stdout.write(`${c}
13
+ `)}),e.stderr.forEach(l=>{let c=Oe(l,r);process.stderr.write(`${c}
14
+ `)});let a=Z(e.success,r);console.log(a)}};function tr(o,e,t){if(e.hasVariable(o)){let r=e.getVariable(o);return r??t}if(e.hasFact(o)){let r=e.getFact(o);return typeof r=="string"?r:String(r)}if(e.hasChoice(o)){let r=e.getChoice(o);return r??t}return t}function ye(o,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return o.replace(t,(r,n)=>tr(n,e,r))}var be=class o{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,r){this.state.stepResults.set(e,{success:t,exitCode:r}),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 o;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 te=class o{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new be,this.taskRunner=new we,this.choicePrompt=new L,this.textPrompt=new me}resolveBaseDir(e){if(e.baseDir)if((0,z.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,z.dirname)(e._filePath);this.baseDir=(0,z.resolve)(t,e.baseDir)}else this.baseDir=(0,z.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let r={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(r.lineNumber=t._lineNumbers.get(e)),t._fileName&&(r.fileName=t._fileName),r}evaluateStepCondition(e){return e.when?new K(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/o.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 r=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)){r.recordStart();try{let g=await this.executeStep(l,c,!1,f);this.handleStepResult(l,c,a,g,r)}catch(g){throw this.handleStepError(l,c,a,g,r),g}}}let s=Date.now()-n,i=X(s);console.log(lt.default.cyan(`
15
+ Total execution time: ${i}`)),await r.save(),r.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,r,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(r);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=Z(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${r}${c} completed, but workflow stopped due to continue: false`:`Step ${r}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${r}${c} failed`)}}}handleStepError(e,t,r,n,s){this.workspace.setStepResult(r,!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 r=e;return"choose"in e&&r.choose===null&&"message"in e&&"options"in e?{choose:{message:r.message,options:r.options,as:r.as},when:r.when}:"prompt"in e&&r.prompt===null&&"message"in e&&"as"in e?{prompt:{message:r.message,as:r.as,default:r.default},when:r.when}:e}async executeStep(e,t,r=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,r,n);return r&&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,r=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run,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,r,n,t.lineNumber,t.fileName,this.baseDir,g,a),S=typeof w=="boolean"?w:w.success;if(h=w,S||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise($=>setTimeout($,v))}}return h}async executeRunStep(e,t,r=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,r,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,r,n)}async executeRunChain(e,t,r,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,r,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,r,n)}async executeChooseStep(e,t){let r=e.choose.as,n=e.choose.options.map(a=>a.id);if(r&&this.workspace.hasVariable(r)){let a=this.workspace.getVariable(r)??"";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=r??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 r=e.prompt.as;if(this.workspace.hasVariable(r)){let a=this.workspace.getVariable(r)??"";this.workspace.setFact(r,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(r,i),this.workspace.setFact(r,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((r,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*o.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 r=[],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 K(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);r.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(r,n[s])},100),a=r.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(r,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(r,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(r,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,r=!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}`});r?(0,Se.default)(n.join(`
16
+ `)):(0,Se.default)(n.join(`
17
+ `))}displayParallelResults(e,t,r){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=ae(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=ot(n);return console.log(i),n}mergeParallelResults(e){for(let t of e){let r=t.workspace.getAllFacts(),n=t.workspace.getAllVariables();for(let[s,i]of r)this.workspace.setFact(s,i);for(let[s,i]of n)this.workspace.setVariable(s,i)}}countExecutableBranches(e,t){let r=0;for(let n=0;n<e.length;n++){let s=e[n],i=t[n];s.when&&!new K(i.workspace).evaluate(s.when)||r++}return r}async executeParallelStep(e,t){let r=this.createParallelContexts(e,t),n=this.countExecutableBranches(e.parallel,r),s=rt(n);console.log(s);let i=await this.executeParallelBranches(e.parallel,r),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(r)}async executeFailStep(e,t){let r=new Error(e.fail.message);throw r.stack=void 0,r}};var ft=require("yaml"),_e=require("zod");var u=require("zod"),rr=u.z.object({file:u.z.string()}),or=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()}),nr=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),sr=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),ir=u.z.object({choice:u.z.string()}),ar=u.z.union([rr,ir,or,nr,sr]),M=u.z.lazy(()=>u.z.union([ar,u.z.object({all:u.z.array(M)}),u.z.object({any:u.z.array(M)}),u.z.object({not:M})])),ct=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:ct.optional()})),ut=u.z.object({run:u.z.string(),when:M.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:ct.optional()}),lr=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:M.optional()}),cr=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:M.optional()});function pt(o){if(!o||typeof o!="object")return{found:!1};let e=o;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 r=pt(t);if(r.found)return r}return{found:!1}}var dt=u.z.lazy(()=>u.z.union([ut,u.z.object({parallel:u.z.array(u.z.lazy(()=>dt)),when:M.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:M.optional()})]).superRefine((o,e)=>{let t=pt(o);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)`})})),ur=u.z.lazy(()=>u.z.union([ut,lr,cr,u.z.object({parallel:u.z.array(dt),when:M.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:M.optional()})])),pr=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))}),dr=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(pr).optional(),steps:u.z.array(ur).min(1,"Workflow must have at least one step")});function Le(o){return dr.parse(o)}function mt(o,e){let t=o.path;if(o.code==="custom"){let n=Be(t);return` - ${o.message}${n}`}if(o.message==="Invalid input"){let n=Be(t),s=fr(t,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let r=Be(t);return` - ${o.message}${r}`}function Be(o){if(o.length===0)return"";let e=[];for(let t=0;t<o.length;t++){let r=o[t],n=o[t+1];r==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),t++):r==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),t++):typeof r=="string"&&r!=="steps"&&r!=="parallel"&&e.push(r)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function b(o,e,t){let r=t?`
18
18
  Reason: ${t}`:"";throw new Error(`Invalid workflow structure:
19
- - ${e} (step ${r+1})${o}`)}function gt(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");b(e,`Unknown step type. Found keys: [${i.join(", ")}]. Valid types: ${n.join(", ")}`)}if(s==="run"){let i=r.run;if(typeof i!="string"&&b(e,"'run' must be a string command"),i===""&&b(e,"'run' command cannot be empty"),"shell"in r&&r.shell!==void 0){Array.isArray(r.shell)||b(e,"'shell' must be an array");let a=r.shell;a.length===0&&b(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"&&b(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 ${o+1})${r}`)}function ht(o,e,t=!1,r=[]){let n=["run","choose","prompt","parallel","fail"],s=n.find(i=>i in o);if(!s){let i=Object.keys(o).filter(a=>a!=="when");b(e,`Unknown step type. Found keys: [${i.join(", ")}]. Valid types: ${n.join(", ")}`)}if(s==="run"){let i=o.run;if(typeof i!="string"&&b(e,"'run' must be a string command"),i===""&&b(e,"'run' command cannot be empty"),"shell"in o&&o.shell!==void 0){Array.isArray(o.shell)||b(e,"'shell' must be an array");let a=o.shell;a.length===0&&b(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"&&b(e,`'shell[${l}]' must be a string`)}}if(s==="choose"){if(t){let l=r.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")&&b(e,"'choose' must be an object with 'message' and 'options'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'choose.message' is required and must be a string"),Array.isArray(a.options)||b(e,"'choose.options' is required and must be an array"),a.options.length===0&&b(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")&&b(e,`'choose.options[${l}]' must be an object with 'id' and 'label'`),(!c.id||typeof c.id!="string")&&b(e,`'choose.options[${l}].id' is required and must be a string`),(!c.label||typeof c.label!="string")&&b(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 i=o.choose;(!i||typeof i!="object")&&b(e,"'choose' must be an object with 'message' and 'options'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'choose.message' is required and must be a string"),Array.isArray(a.options)||b(e,"'choose.options' is required and must be an array"),a.options.length===0&&b(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")&&b(e,`'choose.options[${l}]' must be an object with 'id' and 'label'`),(!c.id||typeof c.id!="string")&&b(e,`'choose.options[${l}].id' is required and must be a string`),(!c.label||typeof c.label!="string")&&b(e,`'choose.options[${l}].label' is required and must be a string`)}}if(s==="prompt"){if(t){let l=r.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")&&b(e,"'prompt' must be an object with 'message' and 'as'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'prompt.message' is required and must be a string"),(!a.as||typeof a.as!="string")&&b(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)||b(e,"'parallel' must be an array of steps"),i.length===0&&b(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")&&b(e,`'parallel[${a}]' must be a valid step object`);let c=[...o,`branch ${a+1}`];gt(l,e,!0,c)}}if(s==="fail"){let i=r.fail;(!i||typeof i!="object")&&b(e,"'fail' must be an object with 'message'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'fail.message' is required and must be a string")}}function wt(r){if(!r||typeof r!="object")throw new Error(`Invalid workflow structure:
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:
23
+ Reason: User input prompts cannot run in parallel`)}let i=o.prompt;(!i||typeof i!="object")&&b(e,"'prompt' must be an object with 'message' and 'as'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'prompt.message' is required and must be a string"),(!a.as||typeof a.as!="string")&&b(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=o.parallel;Array.isArray(i)||b(e,"'parallel' must be an array of steps"),i.length===0&&b(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")&&b(e,`'parallel[${a}]' must be a valid step object`);let c=[...r,`branch ${a+1}`];ht(l,e,!0,c)}}if(s==="fail"){let i=o.fail;(!i||typeof i!="object")&&b(e,"'fail' must be an object with 'message'");let a=i;(!a.message||typeof a.message!="string")&&b(e,"'fail.message' is required and must be a string")}}function gt(o){if(!o||typeof o!="object")throw new Error(`Invalid workflow structure:
24
+ - Workflow must be an object`);let e=o;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:
27
27
  - 'shell' cannot be empty
@@ -30,43 +30,43 @@ Total execution time: ${i}`)),await o.save(),o.reset()}isStepSuccessful(e,t){ret
30
30
  - 'steps' is required`);if(!Array.isArray(e.steps))throw new Error(`Invalid workflow structure:
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
- 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`);gt(o,t)}}function ho(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 Se=class{parse(e){let t;try{t=(0,mt.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)))}wt(t);try{return Le(t)}catch(o){if(o instanceof _e.ZodError){let n=o.issues.map(s=>ht(s,t)).filter(s=>s!==null).join(`
33
+ Reason: Workflow must have at least one step`);for(let t=0;t<e.steps.length;t++){let r=e.steps[t];if(!r||typeof r!="object")throw new Error(`Invalid workflow structure:
34
+ - Step ${t+1} must be an object`);ht(r,t)}}function fr(o,e){try{let t=e;for(let s of o)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(o){let e=o;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))}:o}var ve=class{parse(e){let t;try{t=(0,ft.parse)(e)}catch(r){throw new Error(`Invalid YAML format: ${r instanceof Error?r.message:String(r)}`)}if(t&&typeof t=="object"&&"steps"in t){let r=t;Array.isArray(r.steps)&&(r.steps=r.steps.map(n=>Ve(n)))}gt(t);try{return Le(t)}catch(r){if(r instanceof _e.ZodError){let n=r.issues.map(s=>mt(s,t)).filter(s=>s!==null).join(`
35
35
  `);throw new Error(`Invalid workflow structure:
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}},We=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)))}wt(t);try{return Le(t)}catch(o){if(o instanceof _e.ZodError){let n=o.issues.map(s=>ht(s,t)).filter(s=>s!==null).join(`
36
+ ${n}`)}throw r}}extractStepLineNumbers(e){let t=new Map,r=e.split(`
37
+ `),n=0,s=!1;for(let i=0;i<r.length;i++){let a=r[i].trim();if(a==="steps:"||a.startsWith("steps:")){s=!0;continue}s&&a.startsWith("-")&&t.set(n++,i+1)}return t}},We=class{parse(e){let t;try{t=JSON.parse(e)}catch(r){throw new Error(`Invalid JSON format: ${r instanceof Error?r.message:String(r)}`)}if(t&&typeof t=="object"&&"steps"in t){let r=t;Array.isArray(r.steps)&&(r.steps=r.steps.map(n=>Ve(n)))}gt(t);try{return Le(t)}catch(r){if(r instanceof _e.ZodError){let n=r.issues.map(s=>mt(s,t)).filter(s=>s!==null).join(`
38
38
  `);throw new Error(`Invalid workflow structure:
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 le(r){switch(r.toLowerCase().split(".").pop()){case"yaml":case"yml":return new Se;case"json":return new We;default:return new Se}}var vt=require("fs/promises"),kt=require("path"),ke=y(require("boxen"),1),j=y(require("chalk"),1),ze=y(require("node-cron"),1);ie();var oe=require("fs/promises"),bt=require("os"),He=require("path"),St=(0,He.join)((0,bt.homedir)(),".pipeliner","schedules"),yt=(0,He.join)(St,"schedules.json"),T=class{async loadSchedules(){try{let e=await(0,oe.readFile)(yt,"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,oe.mkdir)(St,{recursive:!0}),await(0,oe.writeFile)(yt,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 go=/^([+-])?(\d{1,2})(?::(\d{2}))?$/;function wo(r){let e=r.trim();if(e===""||e==="0"||e==="+0"||e==="-0")return 0;let t=e.match(go);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 yo(r){if(r===0)return"UTC";let e=r>0?"-":"+",t=Math.abs(r);return`Etc/GMT${e}${t}`}function ve(r){if(!r?.trim())return;let e=wo(r);if(e!==null)return yo(e)}var B=class{scheduleManager;tasks=new Map;startOptions;constructor(){this.scheduleManager=new T}async start(e=!1,t){if(this.startOptions=t,!e&&await A()){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=j.default.bold("\u{1F680} Starting workflow scheduler...");console.log((0,ke.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=[j.default.green("\u2713 Scheduler daemon started"),"",j.default.gray(`PID: ${process.pid}`),j.default.dim(" tp schedule stop stop daemon"),j.default.dim(" tp schedule status check status")].join(`
41
- `);console.log(`${(0,ke.default)(n,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},borderColor:"green"})}
39
+ ${n}`)}throw r}}extractStepLineNumbers(e){let t=new Map,r=e.split(`
40
+ `),n=0,s=!1,i=!1;for(let a=0;a<r.length;a++){let c=r[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 le(o){switch(o.toLowerCase().split(".").pop()){case"yaml":case"yml":return new ve;case"json":return new We;default:return new ve}}var St=require("fs/promises"),vt=require("path"),xe=y(require("boxen"),1),j=y(require("chalk"),1),ze=y(require("node-cron"),1);ie();var re=require("fs/promises"),yt=require("os"),He=require("path"),bt=(0,He.join)((0,yt.homedir)(),".pipeliner","schedules"),wt=(0,He.join)(bt,"schedules.json"),I=class{async loadSchedules(){try{let e=await(0,re.readFile)(wt,"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,re.mkdir)(bt,{recursive:!0}),await(0,re.writeFile)(wt,JSON.stringify({schedules:e},null,2),"utf-8")}async addSchedule(e){let t=await this.loadSchedules(),r=Math.random().toString(36).slice(2,10),n=new Date().toISOString(),s={id:r,createdAt:n,...e};return t.push(s),await this.saveSchedules(t),s}async removeSchedule(e){let t=await this.loadSchedules(),r=t.length,n=t.filter(s=>s.id!==e);return n.length===r?!1:(await this.saveSchedules(n),!0)}async updateLastRun(e){let t=await this.loadSchedules(),r=t.find(n=>n.id===e);r&&(r.lastRun=new Date().toISOString(),await this.saveSchedules(t))}async toggleSchedule(e,t){let r=await this.loadSchedules(),n=r.find(s=>s.id===e);return n?(n.enabled=t,await this.saveSchedules(r),!0):!1}async getSchedule(e){return(await this.loadSchedules()).find(r=>r.id===e)}};var mr=/^([+-])?(\d{1,2})(?::(\d{2}))?$/;function hr(o){let e=o.trim();if(e===""||e==="0"||e==="+0"||e==="-0")return 0;let t=e.match(mr);if(!t)return null;let r=t[1],n=parseInt(t[2],10);if(n>14)return null;let i=r==="-"?-n:n;return i<-12||i>14?null:i}function gr(o){if(o===0)return"UTC";let e=o>0?"-":"+",t=Math.abs(o);return`Etc/GMT${e}${t}`}function ke(o){if(!o?.trim())return;let e=hr(o);if(e!==null)return gr(e)}var B=class{scheduleManager;tasks=new Map;startOptions;constructor(){this.scheduleManager=new I}async start(e=!1,t){if(this.startOptions=t,!e&&await A()){let n=await R();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=j.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=[j.default.green("\u2713 Scheduler daemon started"),"",j.default.gray(`PID: ${process.pid}`),j.default.dim(" tp schedule stop stop daemon"),j.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
42
  `)}}else{let n=[j.default.green("\u2713 Scheduler is running"),j.default.dim(" Press Ctrl+C to stop")].join(`
43
- `);console.log((0,ke.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 se(),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(j.default.gray(` No enabled schedules to load.
45
- `));return}for(let o of t)try{this.startSchedule(o)}catch(n){console.error(j.default.red(` \u2717 Failed to start schedule ${o.id}:`),n)}}startSchedule(e){if(!ze.default.validate(e.cron)){console.error(` \u2717 Invalid cron expression for schedule ${e.id}: ${e.cron}`);return}let t={},o=ve(e.timezone);o&&(t.timezone=o);let n;try{n=ze.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,kt.resolve)(e.workflowPath),n=le(o),s=await(0,vt.readFile)(o,"utf-8"),i=n.parse(s),a=new te,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}
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 A()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(o=>setTimeout(o,500))}return await se(),!0}catch{return await se(),!1}}};var jt=require("child_process"),$e=require("fs"),O=require("path"),Re=y(require("boxen"),1),h=y(require("chalk"),1),Nt=require("commander"),Ee=y(require("dayjs"),1),Y=y(require("inquirer"),1),ce=y(require("log-update"),1),At=y(require("node-cron"),1);ie();var $t=require("fs/promises"),Rt=require("path"),Et=require("yaml"),Pt=require("zod");var P=require("zod"),bo=P.z.object({name:P.z.string().min(1,"Schedule name must be non-empty"),cron:P.z.string().min(1,"Cron expression is required"),workflow:P.z.string().min(1,"Workflow path is required"),baseDir:P.z.string().optional(),timezone:P.z.union([P.z.string(),P.z.number()]).transform(String).optional(),silent:P.z.boolean().optional(),profile:P.z.string().optional()}),So=P.z.object({schedules:P.z.array(bo).min(1,"Schedule file must have at least one schedule")});function xt(r){return So.parse(r)}async function Ct(r){let e=await(0,$t.readFile)(r,"utf-8"),t=(0,Rt.extname)(r).toLowerCase(),o;try{if(t===".yaml"||t===".yml")o=(0,Et.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 xt(o)}catch(n){if(n instanceof Pt.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).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 r=async()=>{e||console.log(`
44
+ \u23F9 Stopping scheduler...`),this.stop(),await se(),e||process.exit(0)};process.on("SIGINT",r),process.on("SIGTERM",r),e&&process.stdin.destroy()}async reload(){this.stop();let t=(await this.scheduleManager.loadSchedules()).filter(r=>r.enabled);if(t.length===0){console.log(j.default.gray(` No enabled schedules to load.
45
+ `));return}for(let r of t)try{this.startSchedule(r)}catch(n){console.error(j.default.red(` \u2717 Failed to start schedule ${r.id}:`),n)}}startSchedule(e){if(!ze.default.validate(e.cron)){console.error(` \u2717 Invalid cron expression for schedule ${e.id}: ${e.cron}`);return}let t={},r=ke(e.timezone);r&&(t.timezone=r);let n;try{n=ze.default.schedule(e.cron,async()=>{await this.executeSchedule(e)},t)}catch(s){throw console.error(` \u2717 Cron schedule failed for ${e.id} (timezone: ${r??"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 r=(0,vt.resolve)(e.workflowPath),n=le(r),s=await(0,St.readFile)(r,"utf-8"),i=n.parse(s),a=new te,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}
47
+ `)}catch(r){e.silent||(console.error(`\u2717 Scheduled workflow failed: ${t}`),console.error(` Error: ${r instanceof Error?r.message:String(r)}
48
+ `))}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async stopDaemon(){let e=await R();if(!e.running||!e.pid)return!1;let t=e.pid;try{if(process.kill(t,"SIGTERM"),await new Promise(r=>setTimeout(r,1e3)),await A()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(r=>setTimeout(r,500))}return await se(),!0}catch{return await se(),!1}}};var Mt=require("child_process"),$e=require("fs"),O=require("path"),Re=y(require("boxen"),1),m=y(require("chalk"),1),jt=require("commander"),Ee=y(require("dayjs"),1),Y=y(require("inquirer"),1),ue=y(require("log-update"),1),Nt=y(require("node-cron"),1);ie();var xt=require("fs/promises"),$t=require("path"),Rt=require("yaml"),Et=require("zod");var P=require("zod"),wr=P.z.object({name:P.z.string().min(1,"Schedule name must be non-empty"),cron:P.z.string().min(1,"Cron expression is required"),workflow:P.z.string().min(1,"Workflow path is required"),baseDir:P.z.string().optional(),timezone:P.z.union([P.z.string(),P.z.number()]).transform(String).optional(),silent:P.z.boolean().optional(),profile:P.z.string().optional()}),yr=P.z.object({schedules:P.z.array(wr).min(1,"Schedule file must have at least one schedule")});function kt(o){return yr.parse(o)}async function Pt(o){let e=await(0,xt.readFile)(o,"utf-8"),t=(0,$t.extname)(o).toLowerCase(),r;try{if(t===".yaml"||t===".yml")r=(0,Rt.parse)(e);else if(t===".json")r=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 kt(r)}catch(n){if(n instanceof Et.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).join(`
49
49
  `);throw new Error(`Invalid schedule file structure:
50
- ${s}`)}throw n}}var Dt=y(require("boxen"),1),S=y(require("chalk"),1),Tt=y(require("cronstrue"),1),Ye=y(require("dayjs"),1),Ue=y(require("node-cron"),1);function Je(r){try{return Tt.default.toString(r)}catch{return null}}function vo(r){if(!Ue.default.validate(r.cron))return null;try{let e={},t=ve(r.timezone);t&&(e.timezone=t);let o=Ue.default.createTask(r.cron,()=>{},e),n=o.getNextRun();return o.destroy(),n}catch{return null}}function xe(r,e){let t=r,{daemonRunning:o}=e,n=t.enabled?S.default.green("enabled"):S.default.gray("disabled"),s=o&&t.enabled,i=s?S.default.green("\u25CF active"):S.default.gray("\u25CB inactive"),a=S.default.bold(t.name??t.workflowPath),l=vo(t),c=l?(0,Ye.default)(l).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("\u2014"),f=t.lastRun?(0,Ye.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("never"),g=Je(t.cron),m=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,d=[[S.default.gray("Enabled"),n],[S.default.gray("Cron"),t.cron],...g?[[S.default.gray(""),S.default.dim(`\u2192 ${g}`)]]:[],...m?[[S.default.gray("Timezone"),m]]:[],[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"),f],[S.default.gray("Next run"),c]],w=[`${a} ${i}`,...d.map(([k,R])=>` ${k.padEnd(10)} ${R}`)].join(`
51
- `);return(0,Dt.default)(w,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:s?"green":"gray"})}function Ot(){let r=new Nt.Command("schedule").description("Manage workflow schedules").action(async()=>{await It()});return r.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON)").action(async e=>{await ko(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await xo()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await To()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await It()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await $o(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 Co(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await Do()}),r}function qe(r,e){let t=e.workflow;if((0,O.isAbsolute)(t))return t;let o=e.baseDir?(0,O.resolve)(e.baseDir):(0,O.dirname)(r);return(0,O.resolve)(o,t)}async function ko(r){let e=new T;if(!r){let{path:a}=await Y.default.prompt([{type:"input",name:"path",message:"Schedule file path (YAML or JSON):",validate:l=>{let c=(0,O.resolve)(l);return(0,$e.existsSync)(c)?!0:`File not found: ${c}`}}]);r=a}let t=(0,O.resolve)(r);(0,$e.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let o;try{o=await Ct(t)}catch(a){console.error(`\u2717 Failed to parse schedule file: ${a instanceof Error?a.message:String(a)}`),process.exit(1)}let n=o.schedules.filter(a=>!At.default.validate(a.cron));if(n.length>0){console.error("\u2717 Invalid cron expression(s):");for(let a of n)console.error(` - ${a.name}: "${a.cron}"`);process.exit(1)}let s=o.schedules.filter(a=>{let l=qe(t,a);return!(0,$e.existsSync)(l)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let a of s){let l=qe(t,a);console.error(` - ${a.name}: ${a.workflow} (resolved: ${l})`)}process.exit(1)}console.log(`
52
- Found ${o.schedules.length} schedule(s) in file.
53
- `);let i=[];for(let a of o.schedules){let{alias:l}=await Y.default.prompt([{type:"input",name:"alias",message:`Alias for "${a.name}" (press Enter to use as-is):`,default:a.name}]),c=await e.addSchedule({name:l,workflowPath:qe(t,a),cron:a.cron,enabled:!0,timezone:a.timezone,silent:a.silent,profile:a.profile});i.push(c)}console.log(`
50
+ ${s}`)}throw n}}var Ct=y(require("boxen"),1),k=y(require("chalk"),1),Dt=y(require("cronstrue"),1),Ye=y(require("dayjs"),1),Ue=y(require("node-cron"),1);function br(o){try{return Dt.default.toString(o)}catch{return null}}function Sr(o){if(!Ue.default.validate(o.cron))return null;try{let e={},t=ke(o.timezone);t&&(e.timezone=t);let r=Ue.default.createTask(o.cron,()=>{},e),n=r.getNextRun();return r.destroy(),n}catch{return null}}function ce(o,e){let t=o,{daemonRunning:r}=e,n=t.enabled?k.default.green("enabled"):k.default.gray("disabled"),s=r&&t.enabled,i=s?k.default.green("\u25CF active"):k.default.gray("\u25CB inactive"),a=k.default.bold(t.name??t.workflowPath),l=Sr(t),c=l?(0,Ye.default)(l).format("YYYY-MM-DD HH:mm:ss"):k.default.dim("\u2014"),f=t.lastRun?(0,Ye.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):k.default.dim("never"),g=br(t.cron),h=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,d=g?`${t.cron} ${k.default.dim(`\u2192 ${g}`)}`:t.cron,w=[[k.default.gray("Enabled"),n],[k.default.gray("Cron"),d],...h?[[k.default.gray("Timezone"),h]]:[],[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"),c]],S=[`${a} ${i}`,...w.map(([$,C])=>` ${$.padEnd(10)} ${C}`)].join(`
51
+ `);return(0,Ct.default)(S,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:s?"green":"gray"})}function At(){let o=new jt.Command("schedule").description("Manage workflow schedules").action(async()=>{await Tt()});return o.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON)").action(async e=>{await vr(e)}),o.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await kr()}),o.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Dr()}),o.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await Tt()}),o.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await xr(e.daemon??!1)}),o.command("stop").description("Stop the scheduler daemon").action(async()=>{await $r()}),o.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 Pr(t)}),o.command("toggle").description("Enable or disable a schedule").action(async()=>{await Cr()}),o}function Je(o,e){let t=e.workflow;if((0,O.isAbsolute)(t))return t;let r=e.baseDir?(0,O.resolve)(e.baseDir):(0,O.dirname)(o);return(0,O.resolve)(r,t)}async function vr(o){let e=new I;if(!o){let{path:l}=await Y.default.prompt([{type:"input",name:"path",message:"Schedule file path (YAML or JSON):",validate:c=>{let f=(0,O.resolve)(c);return(0,$e.existsSync)(f)?!0:`File not found: ${f}`}}]);o=l}let t=(0,O.resolve)(o);(0,$e.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let r;try{r=await Pt(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let n=r.schedules.filter(l=>!Nt.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=r.schedules.filter(l=>{let c=Je(t,l);return!(0,$e.existsSync)(c)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of s){let c=Je(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
52
+ Found ${r.schedules.length} schedule(s) in file.
53
+ `);let i=[];for(let l of r.schedules){let{alias:c}=await Y.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:Je(t,l),cron:l.cron,enabled:!0,timezone:l.timezone,silent:l.silent,profile:l.profile});i.push(f)}let a=await R();console.log(`
54
54
  \u2713 Added ${i.length} schedule(s) successfully
55
- `);for(let a of i){let l=Je(a.cron);console.log(` - ${a.name??"N/A"}`),console.log(` Cron: ${a.cron}`),l&&console.log(` ${h.default.dim(`\u2192 ${l}`)}`),a.timezone&&console.log(` Timezone: ${a.timezone}`),console.log(` Workflow: ${a.workflowPath}`),a.silent&&console.log(" Silent: Yes"),a.profile&&console.log(` Profile: ${a.profile}`),console.log(` Status: ${a.enabled?"Enabled":"Disabled"}`),console.log()}console.log('Run "tp schedule start" to start the scheduler daemon')}async function xo(){let r=new T,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{scheduleId:t}=await Y.default.prompt([{type:"list",name:"scheduleId",message:"Select schedule to remove:",choices:e.map(s=>({name:`${s.name??s.workflowPath} (${s.cron}) ${s.enabled?"\u2713":"\u2717"}`,value:s.id}))}]),{confirm:o}=await Y.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!o){console.log("Cancelled");return}let n=await r.removeSchedule(t);console.log(n?"\u2713 Schedule removed successfully":"\u2717 Schedule not found")}async function It(){let e=await new T().loadSchedules();if(e.length===0){let i=[h.default.gray("No schedules registered."),"",h.default.dim(" tp schedule add <schedule.yaml> add from a schedule file")].join(`
55
+ `);for(let l of i)console.log(ce(l,{daemonRunning:a.running}));console.log(m.default.dim(' Tip: Run "tp schedule start" to start the scheduler daemon'))}async function kr(){let o=new I,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{scheduleId:t}=await Y.default.prompt([{type:"list",name:"scheduleId",message:"Select schedule to remove:",choices:e.map(s=>({name:`${s.name??s.workflowPath} (${s.cron}) ${s.enabled?"\u2713":"\u2717"}`,value:s.id}))}]),{confirm:r}=await Y.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!r){console.log("Cancelled");return}let n=await o.removeSchedule(t);console.log(n?"\u2713 Schedule removed successfully":"\u2717 Schedule not found")}async function Tt(){let e=await new I().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(`
56
56
  `);console.log(`
57
57
  ${(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"})}
58
- `);return}let t=await $(),o=t.running?h.default.green("\u25CF running"):h.default.gray("\u25CB stopped"),n=e.filter(i=>i.enabled).length,s=h.default.bold("\u{1F4C5} Workflow Schedules");console.log(s),console.log([h.default.gray(" Daemon: "),o,h.default.gray(` \xB7 Schedules: ${n}/${e.length} enabled`)].join(""));for(let i of e)console.log(xe(i,{daemonRunning:t.running}));console.log(h.default.dim(" Tip: tp schedule start \u2014 run scheduler daemon; tp schedule status \u2014 view live status"))}async function $o(r){if(await A()){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(()=>(ie(),et));await e(),await new B().start(!0),await new Promise(()=>{})}catch(e){await Ie(e instanceof Error?e:new Error(String(e))),process.exit(1)}else{let e=process.argv.slice(1);(0,jt.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 A()){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(h.default.dim(" Last error from daemon:")),console.error(h.default.red(i.split(`
58
+ `);return}let t=await R(),r=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: "),r,m.default.gray(` \xB7 Schedules: ${n}/${e.length} enabled`)].join(""));for(let i of e)console.log(ce(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 xr(o){if(await A()){let e=await R();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(o)if(process.env.TP_DAEMON_MODE==="true")try{let{saveDaemonPid:e}=await Promise.resolve().then(()=>(ie(),Qe));await e(),await new B().start(!0),await new Promise(()=>{})}catch(e){await Ie(e instanceof Error?e:new Error(String(e))),process.exit(1)}else{let e=process.argv.slice(1);(0,Mt.spawn)(process.argv[0],e,{detached:!0,stdio:"ignore",env:{...process.env,TP_DAEMON_MODE:"true"}}).unref();let r=3,n=800,s=!1;for(let i=0;i<r;i++)if(await new Promise(a=>setTimeout(a,n)),await A()){s=!0;break}if(s){let i=await R();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(`
59
59
  `).map(a=>` ${a}`).join(`
60
- `)))):console.error(h.default.dim(` Check ${Me()} for details`)),process.exit(1)}process.exit(0)}else await new B().start(!1,{onScheduleStarted:t=>console.log(xe(t,{daemonRunning:!0}))}),await new Promise(()=>{})}async function Ro(){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 B().stopDaemon();console.log(t?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}function Eo(r){if(!r)return"Unknown";let e=(0,Ee.default)(r),o=(0,Ee.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 Po(r,e){return xe(r,{daemonRunning:e})}async function Ge(){let r=await $(),t=await new T().loadSchedules(),o=[],n;if(r.running&&r.pid){let i=Eo(r.startTime),a=r.startTime?(0,Ee.default)(r.startTime).format("YYYY-MM-DD HH:mm:ss"):"Unknown";n=[`${h.default.green("\u25CF")} ${h.default.green("active")} ${h.default.gray("(running)")}`,"",`${h.default.gray("Loaded:")} ${h.default.white(a)}`,`${h.default.gray("Active:")} ${h.default.green("active (running)")} since ${h.default.white(a)}`,`${h.default.gray("PID:")} ${h.default.white(r.pid.toString())}`,`${h.default.gray("Uptime:")} ${h.default.white(i)}`].join(`
61
- `)}else n=[`${h.default.red("\u25CF")} ${h.default.red("inactive")} ${h.default.gray("(dead)")}`,"",`${h.default.gray("Loaded:")} ${h.default.gray("not found")}`,`${h.default.gray("Active:")} ${h.default.red("inactive (dead)")}`].join(`
62
- `);let s=(0,Re.default)(n,{title:h.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=h.default.bold(`Schedules: ${i}/${t.length} enabled`);o.push(a);for(let l of t)o.push(Po(l,r.running))}else{let i=(0,Re.default)(h.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(`
63
- `)}function Mt(){process.stdout.write("\x1B[2J\x1B[H")}async function Co(r){if(r){let e=!0,t=()=>{e=!1,ce.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 Ge(),c=(await $()).running?h.default.gray(`
64
- Press Ctrl+C to exit this view (daemon keeps running in background)`):h.default.gray(`
65
- Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,ce.default)(`${a}${c}`)}catch(a){ce.default.done(),console.error("Error updating status:",a),clearInterval(o),process.exit(1)}},1e3);Mt();let n=await Ge(),i=(await $()).running?h.default.gray(`
66
- Press Ctrl+C to exit this view (daemon keeps running in background)`):h.default.gray(`
67
- Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,ce.default)(`${n}${i}`),await new Promise(()=>{})}else{Mt();let e=await Ge(),o=(await $()).running?"":h.default.gray(`
68
- Tip: To start the daemon, run: tp schedule start -d`);console.log(`${e}${o}
69
- `)}}async function Do(){let r=new T,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{scheduleId:t}=await Y.default.prompt([{type:"list",name:"scheduleId",message:"Select schedule to toggle:",choices:e.map(s=>({name:`${s.name??s.workflowPath} (${s.cron}) ${s.enabled?"\u2713":"\u2717"}`,value:s.id}))}]),o=e.find(s=>s.id===t);if(!o){console.log("\u2717 Schedule not found");return}let n=!o.enabled;await r.toggleSchedule(t,n),console.log(`\u2713 Schedule ${n?"enabled":"disabled"}: ${o.name??o.workflowPath}`)}async function To(){let r=new T,e=await r.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:t}=await Y.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 F=require("fs"),E=require("path"),Ze=require("url"),Ft={};function Lt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function Bt(){return"0.3.0"}function Wt(r){let e=r?(0,E.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,E.resolve)(e,"tp");try{if((0,F.existsSync)(n)&&(0,F.statSync)(n).isDirectory())return n}catch{}let s=(0,E.dirname)(e);if(s===e)break;e=s,o++}return null}var ue=(0,U.join)((0,Vt.homedir)(),".pipeliner"),Io=(0,Ht.promisify)(_t.exec),J=new zt.Command;J.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
60
+ `)))):console.error(m.default.dim(` Check ${Me()} for details`)),process.exit(1)}process.exit(0)}else await new B().start(!1,{onScheduleStarted:t=>console.log(ce(t,{daemonRunning:!0}))}),await new Promise(()=>{})}async function $r(){let o=await R();if(!o.running){console.log("Scheduler daemon is not running");return}console.log(`Stopping scheduler daemon (PID: ${o.pid})...`);let t=await new B().stopDaemon();console.log(t?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}function Rr(o){if(!o)return"Unknown";let e=(0,Ee.default)(o),r=(0,Ee.default)().diff(e,"second"),n=Math.floor(r/86400),s=Math.floor(r%86400/3600),i=Math.floor(r%3600/60),a=r%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 Er(o,e){return ce(o,{daemonRunning:e})}async function qe(){let o=await R(),t=await new I().loadSchedules(),r=[],n;if(o.running&&o.pid){let i=Rr(o.startTime),a=o.startTime?(0,Ee.default)(o.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(o.pid.toString())}`,`${m.default.gray("Uptime:")} ${m.default.white(i)}`].join(`
61
+ `)}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(`
62
+ `);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:o.running?"green":"red"});if(r.push(s),t.length>0){let i=t.filter(l=>l.enabled).length,a=m.default.bold(`Schedules: ${i}/${t.length} enabled`);r.push(a);for(let l of t)r.push(Er(l,o.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"});r.push(i)}return r.join(`
63
+ `)}function It(){process.stdout.write("\x1B[2J\x1B[H")}async function Pr(o){if(o){let e=!0,t=()=>{e=!1,ue.default.done(),process.exit(0)};process.on("SIGINT",t),process.on("SIGTERM",t);let r=setInterval(async()=>{if(!e){clearInterval(r);return}try{let a=await qe(),c=(await R()).running?m.default.gray(`
64
+ Press Ctrl+C to exit this view (daemon keeps running in background)`):m.default.gray(`
65
+ Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,ue.default)(`${a}${c}`)}catch(a){ue.default.done(),console.error("Error updating status:",a),clearInterval(r),process.exit(1)}},1e3);It();let n=await qe(),i=(await R()).running?m.default.gray(`
66
+ Press Ctrl+C to exit this view (daemon keeps running in background)`):m.default.gray(`
67
+ Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit this view.`);(0,ue.default)(`${n}${i}`),await new Promise(()=>{})}else{It();let e=await qe(),r=(await R()).running?"":m.default.gray(`
68
+ Tip: To start the daemon, run: tp schedule start -d`);console.log(`${e}${r}
69
+ `)}}async function Cr(){let o=new I,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{scheduleId:t}=await Y.default.prompt([{type:"list",name:"scheduleId",message:"Select schedule to toggle:",choices:e.map(s=>({name:`${s.name??s.workflowPath} (${s.cron}) ${s.enabled?"\u2713":"\u2717"}`,value:s.id}))}]),r=e.find(s=>s.id===t);if(!r){console.log("\u2717 Schedule not found");return}let n=!r.enabled;await o.toggleSchedule(t,n),console.log(`\u2713 Schedule ${n?"enabled":"disabled"}: ${r.name??r.workflowPath}`)}async function Dr(){let o=new I,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:t}=await Y.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 o.saveSchedules([]),console.log(`\u2713 Removed all ${e.length} schedule(s)`)}var F=require("fs"),E=require("path"),Ge=require("url"),Ot={};function Ft(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function Lt(){return"0.3.2"}function Bt(o){let e=o?(0,E.resolve)(o):process.cwd(),t=50,r=0;for(;r<t;){let n=(0,E.resolve)(e,"tp");try{if((0,F.existsSync)(n)&&(0,F.statSync)(n).isDirectory())return n}catch{}let s=(0,E.dirname)(e);if(s===e)break;e=s,r++}return null}var pe=(0,U.join)((0,_t.homedir)(),".pipeliner"),Tr=(0,Vt.promisify)(Wt.exec),J=new Ht.Command;J.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
70
70
 
71
71
  Define workflows in YAML or JSON files with conditional execution, parallel tasks,
72
72
  interactive prompts, variable substitution, and cron-based scheduling.
@@ -119,7 +119,7 @@ Quick Start:
119
119
 
120
120
  Note: After upgrading to a new version, if you see compatibility issues (e.g. schedules or daemon), run "tp clean" to reset ~/.pipeliner data.
121
121
 
122
- `).version(Bt()).addHelpText("after",`
122
+ `).version(Lt()).addHelpText("after",`
123
123
  Examples:
124
124
  $ tp run workflow.yaml
125
125
  $ tp run workflow.yaml --profile Production
@@ -164,44 +164,44 @@ Workflow File Structure:
164
164
  \u2022 all/any/not: Combine conditions
165
165
 
166
166
  Supported formats: YAML (.yaml, .yml) and JSON (.json)
167
- See README.md for complete DSL documentation.`).action(async(r,e)=>{try{let t=r??await jo()??null;t||(console.error(p.default.red(`
168
- \u2717 No workflow file found`)),process.exit(1)),e.silent&&Lt();let o=le(t);console.log(p.default.blue(`Loading workflow from ${t}...`));let n=(0,pe.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=No(t),s._filePath=(0,U.resolve)(t),console.log(p.default.green(`Starting workflow execution...
167
+ See README.md for complete DSL documentation.`).action(async(o,e)=>{try{let t=o??await Mr()??null;t||(console.error(p.default.red(`
168
+ \u2717 No workflow file found`)),process.exit(1)),e.silent&&Ft();let r=le(t);console.log(p.default.blue(`Loading workflow from ${t}...`));let n=(0,de.readFileSync)(t,"utf-8"),s=r.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=r.extractStepLineNumbers(n),s._fileName=jr(t),s._filePath=(0,U.resolve)(t),console.log(p.default.green(`Starting workflow execution...
169
169
  `)),await new te().execute(s,i?{profileVars:i}:void 0),console.log(p.default.green(`
170
- \u2713 Workflow completed successfully`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(p.default.red(`
171
- \u2717 Workflow failed: ${o}`)),process.exit(1)}});J.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
170
+ \u2713 Workflow completed successfully`))}catch(t){let r=t instanceof Error?t.message:String(t);console.error(p.default.red(`
171
+ \u2717 Workflow failed: ${r}`)),process.exit(1)}});J.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
172
172
  Examples:
173
173
  $ tp open generator
174
174
  $ tp open docs
175
175
 
176
176
  Targets:
177
177
  generator Open the visual workflow generator (https://task-pipeliner-generator.racgoo.com/)
178
- 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(`
179
- \u2717 Invalid target: ${r}`)),console.log(p.default.yellow(`
180
- 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 Io(n),console.log(p.default.green(`
181
- \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(`
178
+ docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(async o=>{let t={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[o.toLowerCase()];t||(console.error(p.default.red(`
179
+ \u2717 Invalid target: ${o}`)),console.log(p.default.yellow(`
180
+ 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 r=process.platform,n;r==="darwin"?n=`open "${t}"`:r==="win32"?n=`start "${t}"`:n=`xdg-open "${t}"`,await Tr(n),console.log(p.default.green(`
181
+ \u2713 Opening ${o==="generator"?"generator":"documentation"} in browser...`)),console.log(p.default.blue(` ${t}`))}catch(r){let n=r instanceof Error?r.message:String(r);console.error(p.default.red(`
182
182
  \u2717 Failed to open browser: ${n}`)),console.log(p.default.yellow(`
183
- Please visit manually: ${t}`)),process.exit(1)}});J.addCommand(Ot());var Mo=J.command("history").description("Manage workflow execution history");Mo.action(async()=>{let r=new L,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(`
184
- \u2717 Invalid choice`)),process.exit(1));let t=new ee;switch(e.id){case"show":{let o=await t.getHistoryNames();if(o.length===0){console.log(p.default.yellow(`
185
- \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(`
186
- \u2717 Invalid choice`)),process.exit(1));try{let s=await t.getHistory(n.id);Ao(s,n.id)}catch(s){let i=s instanceof Error?s.message:String(s);console.error(p.default.red(`
187
- \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(`
188
- \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(`
183
+ Please visit manually: ${t}`)),process.exit(1)}});J.addCommand(At());var Ir=J.command("history").description("Manage workflow execution history");Ir.action(async()=>{let o=new L,e=await o.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(`
184
+ \u2717 Invalid choice`)),process.exit(1));let t=new ee;switch(e.id){case"show":{let r=await t.getHistoryNames();if(r.length===0){console.log(p.default.yellow(`
185
+ \u26A0 No history found`));return}let n=await o.prompt("Select a history to view",r.map(s=>({id:s,label:s})));n?.id||(console.error(p.default.red(`
186
+ \u2717 Invalid choice`)),process.exit(1));try{let s=await t.getHistory(n.id);Nr(s,n.id)}catch(s){let i=s instanceof Error?s.message:String(s);console.error(p.default.red(`
187
+ \u2717 Failed to load history: ${i}`)),process.exit(1)}break}case"remove":{let r=await t.getHistoryNames();if(r.length===0){console.log(p.default.yellow(`
188
+ \u26A0 No history found`));return}let n=await o.prompt("Select a history to remove",r.map(s=>({id:s,label:s})));n?.id||(console.error(p.default.red(`
189
189
  \u2717 Invalid choice`)),process.exit(1));try{await t.removeHistory(n.id),console.log(p.default.green(`
190
190
  \u2713 Removed history: ${n.id}`))}catch(s){let i=s instanceof Error?s.message:String(s);console.error(p.default.red(`
191
- \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(`
191
+ \u2717 Failed to remove history: ${i}`)),process.exit(1)}break}case"remove-all":{if((await o.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(`
192
192
  \u2717 Cancelled`));return}try{await t.clearAllHistories(),console.log(p.default.green(`
193
193
  \u2713 All histories removed`))}catch(n){let s=n instanceof Error?n.message:String(n);console.error(p.default.red(`
194
194
  \u2717 Failed to remove histories: ${s}`)),process.exit(1)}break}default:console.error(p.default.red(`
195
- \u2717 Unknown action: ${e.id}`)),process.exit(1)}});async function jo(){let r=Wt();if(!r)return console.error(p.default.red(`
196
- \u2717 No tp directory found`)),null;try{let t=(await(0,Pe.readdir)(r)).filter(i=>{let a=(0,U.extname)(i).toLowerCase();return[".yaml",".yml",".json"].includes(a)});if(t.length===0)return console.error(p.default.red(`
197
- \u2717 No workflow files found in ${r}`)),null;let o=await Promise.all(t.map(async i=>{let a=(0,U.join)(r,i);try{let l=le(a),c=(0,pe.readFileSync)(a,"utf-8"),g=l.parse(c).name??"Untitled";return{id:a,label:`${i} - ${g}`}}catch{return{id:a,label:i}}}));return(await new L(!0).prompt("Select a workflow to run",o)).id}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(p.default.red(`
198
- \u2717 Failed to read tp directory: ${t}`)),null}}function No(r){return r.split("/").pop()??r}function Ao(r,e){console.log(`
199
- `);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,Yt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=X(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(`
200
- `);console.log((0,Xe.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:"cyan"})),r.records.forEach((c,f)=>{Oo(c,f+1,r.records.length)}),console.log("")}function Oo(r,e,t){let o=Fo(r.step),n=Lo(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=X(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(`
201
- `);console.log((0,Xe.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Bo(r.output)&&Wo(r.output)}function Fo(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Lo(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 Bo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function Wo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
202
- `);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(`
203
- `);console.log(p.default.red(" Errors:")),console.log(e)}}J.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 L().prompt(`This will remove all data in ${p.default.yellow(ue)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
204
- \u2717 Cancelled`));return}try{if(await A()){let t=await $();console.log(p.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new B().stopDaemon(),console.log(p.default.gray(" Daemon stopped"))}(0,pe.existsSync)(ue)?(await(0,Pe.rm)(ue,{recursive:!0}),console.log(p.default.green(`
205
- \u2713 Removed ${ue}`))):console.log(p.default.gray(`
206
- ${ue} does not exist (already clean)`))}catch(t){let o=t instanceof Error?t.message:String(t);console.error(p.default.red(`
207
- \u2717 Clean failed: ${o}`)),process.exit(1)}});J.parse();
195
+ \u2717 Unknown action: ${e.id}`)),process.exit(1)}});async function Mr(){let o=Bt();if(!o)return console.error(p.default.red(`
196
+ \u2717 No tp directory found`)),null;try{let t=(await(0,Pe.readdir)(o)).filter(i=>{let a=(0,U.extname)(i).toLowerCase();return[".yaml",".yml",".json"].includes(a)});if(t.length===0)return console.error(p.default.red(`
197
+ \u2717 No workflow files found in ${o}`)),null;let r=await Promise.all(t.map(async i=>{let a=(0,U.join)(o,i);try{let l=le(a),c=(0,de.readFileSync)(a,"utf-8"),g=l.parse(c).name??"Untitled";return{id:a,label:`${i} - ${g}`}}catch{return{id:a,label:i}}}));return(await new L(!0).prompt("Select a workflow to run",r)).id}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(p.default.red(`
198
+ \u2717 Failed to read tp directory: ${t}`)),null}}function jr(o){return o.split("/").pop()??o}function Nr(o,e){console.log(`
199
+ `);let t=o.records.reduce((c,f)=>c+f.duration,0),r=o.records.filter(c=>c.status==="success").length,n=o.records.filter(c=>c.status==="failure").length,s=(0,zt.default)(o.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=X(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:")} ${o.records.length}`,`${p.default.green("\u2713 Successful:")} ${r}`,n>0?`${p.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
200
+ `);console.log((0,Ze.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:"cyan"})),o.records.forEach((c,f)=>{Ar(c,f+1,o.records.length)}),console.log("")}function Ar(o,e,t){let r=Or(o.step),n=Fr(o.step),s=o.status==="success"?p.default.green("\u2713"):p.default.red("\u2717"),i=o.status==="success"?p.default.green("Success"):p.default.red("Failed"),a=X(o.duration),l=[`${s} ${p.default.bold(`Step ${e}/${t}`)} - ${p.default.cyan(r)}`,`${p.default.gray("Duration:")} ${a} | ${p.default.gray("Status:")} ${i}`,"",p.default.white(n)].join(`
201
+ `);console.log((0,Ze.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:o.status==="success"?"green":"red"})),Lr(o.output)&&Br(o.output)}function Or(o){return"run"in o?"Run":"choose"in o?"Choose":"prompt"in o?"Prompt":"parallel"in o?"Parallel":"fail"in o?"Fail":"Unknown"}function Fr(o){return"run"in o?`Command: ${p.default.yellow(o.run)}`:"choose"in o?`Message: ${p.default.yellow(o.choose.message)}`:"prompt"in o?`Message: ${p.default.yellow(o.prompt.message)} | Variable: ${p.default.cyan(o.prompt.as)}`:"parallel"in o?`Parallel execution with ${o.parallel.length} branches`:"fail"in o?`Error: ${p.default.red(o.fail.message)}`:"Unknown step type"}function Lr(o){return typeof o=="object"&&o!==null&&"success"in o&&"stdout"in o&&"stderr"in o}function Br(o){if(o.stdout.length>0){let e=o.stdout.map(t=>p.default.gray(` ${t}`)).join(`
202
+ `);console.log(p.default.green(" Output:")),console.log(e)}if(o.stderr.length>0){let e=o.stderr.map(t=>p.default.gray(` ${t}`)).join(`
203
+ `);console.log(p.default.red(" Errors:")),console.log(e)}}J.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 L().prompt(`This will remove all data in ${p.default.yellow(pe)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
204
+ \u2717 Cancelled`));return}try{if(await A()){let t=await R();console.log(p.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new B().stopDaemon(),console.log(p.default.gray(" Daemon stopped"))}(0,de.existsSync)(pe)?(await(0,Pe.rm)(pe,{recursive:!0}),console.log(p.default.green(`
205
+ \u2713 Removed ${pe}`))):console.log(p.default.gray(`
206
+ ${pe} does not exist (already clean)`))}catch(t){let r=t instanceof Error?t.message:String(t);console.error(p.default.red(`
207
+ \u2717 Clean failed: ${r}`)),process.exit(1)}});J.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeliner",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "A task pipeline runner with condition-based workflow execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -10,12 +10,27 @@
10
10
  "tp": "./dist/index.cjs"
11
11
  },
12
12
  "keywords": [
13
- "task",
14
- "pipeline",
13
+ "workflow-orchestration",
15
14
  "workflow",
15
+ "orchestration",
16
+ "task-runner",
17
+ "task-automation",
18
+ "ci-cd",
19
+ "build-automation",
20
+ "devops",
16
21
  "automation",
22
+ "pipeline",
23
+ "workflow-engine",
24
+ "yaml",
25
+ "json",
26
+ "scheduler",
27
+ "cron",
17
28
  "cli",
18
- "interactive"
29
+ "interactive",
30
+ "makefile-alternative",
31
+ "bash-alternative",
32
+ "deployment",
33
+ "build-tool"
19
34
  ],
20
35
  "author": "racgoo",
21
36
  "license": "MIT",