@r5n/hydra 0.5.7 → 0.6.0
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/LICENSE +1 -201
- package/README.md +97 -279
- package/dist/cli.js +95 -81
- package/package.json +9 -8
package/dist/cli.js
CHANGED
|
@@ -1,84 +1,98 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
`).
|
|
5
|
-
`)
|
|
6
|
-
`)
|
|
7
|
-
`),i=r.split(`
|
|
8
|
-
`),
|
|
9
|
-
`),
|
|
10
|
-
`).length
|
|
11
|
-
`)
|
|
12
|
-
`).
|
|
13
|
-
`)
|
|
14
|
-
`)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`,`
|
|
18
|
-
|
|
19
|
-
`).
|
|
20
|
-
`)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
${
|
|
28
|
-
${
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
`)
|
|
32
|
-
`)
|
|
33
|
-
${
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
`
|
|
37
|
-
`)
|
|
38
|
-
`)
|
|
39
|
-
`)
|
|
40
|
-
`)
|
|
41
|
-
${
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
${
|
|
46
|
-
`
|
|
47
|
-
${
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
${g.default.yellow(hn)}${c}
|
|
51
|
-
`}case"submit":{let c=s?` ${g.default.dim(s)}`:"";return`${r}${g.default.gray(M)}${c}`}case"cancel":{let c=s?` ${g.default.strikethrough(g.default.dim(s))}`:"";return`${r}${g.default.gray(M)}${c}${s.trim()?`
|
|
52
|
-
${g.default.gray(M)}`:""}`}default:return`${r}${g.default.cyan(M)} ${i}
|
|
53
|
-
${g.default.cyan(hn)}
|
|
54
|
-
`}}}).prompt();var I=O(()=>{xr();xr();g=Cn(ar(),1),kn=Cn(ur(),1);er=Rs(),Es=H("\u25C6","*"),No=H("\u25A0","x"),Po=H("\u25B2","x"),Sr=H("\u25C7","o"),es=H("\u250C","T"),M=H("\u2502","|"),hn=H("\u2514","\u2014"),Pa=H("\u2510","T"),Ua=H("\u2518","\u2014"),Cr=H("\u25CF",">"),Wn=H("\u25CB"," "),Ma=H("\u25FB","[\u2022]"),La=H("\u25FC","[+]"),ja=H("\u25FB","[ ]"),qa=H("\u25AA","\u2022"),Ba=H("\u2500","-"),Va=H("\u256E","+"),za=H("\u251C","+"),Aa=H("\u256F","+"),Da=H("\u2570","+"),Ia=H("\u256D","+"),Cs=H("\u25CF","\u2022"),Os=H("\u25C6","*"),Ss=H("\u25B2","!"),ks=H("\u25A0","x"),Rr=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/y,Dn=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,In=/\t{1,1000}/y,$r=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu,Kn=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Ns=/\p{M}+/gu,Ps={limit:1/0,ellipsis:""},Us={limit:1/0,ellipsis:"",ellipsisWidth:0},Hr=`${Ls}8;;`,_o=new RegExp(`(?:\\${Lo}(?<code>\\d+)m|\\${Hr}(?<uri>.*)${_r})`,"y");w={message:(n=[],{symbol:r=g.default.gray(M),secondarySymbol:o=g.default.gray(M),output:i=process.stdout,spacing:s=1}={})=>{let c=[];for(let u=0;u<s;u++)c.push(`${o}`);let a=Array.isArray(n)?n:n.split(`
|
|
55
|
-
`);if(a.length>0){let[u,...t]=a;u.length>0?c.push(`${r} ${u}`):c.push(r);for(let f of t)f.length>0?c.push(`${o} ${f}`):c.push(o)}i.write(`${c.join(`
|
|
2
|
+
// @bun
|
|
3
|
+
var _o=Object.create;var{getPrototypeOf:To,defineProperty:zn,getOwnPropertyNames:ri}=Object;var ni=Object.prototype.hasOwnProperty;function oi(r){return this[r]}var ii,ei,Wn=(r,n,o)=>{var i=r!=null&&typeof r==="object";if(i){var e=n?ii??=new WeakMap:ei??=new WeakMap,t=e.get(r);if(t)return t}o=r!=null?_o(To(r)):{};let a=n||!r||!r.__esModule?zn(o,"default",{value:r,enumerable:!0}):o;for(let s of ri(r))if(!ni.call(a,s))zn(a,s,{get:oi.bind(r,s),enumerable:!0});if(i)e.set(r,a);return a};var ti=(r,n)=>()=>(n||r((n={exports:{}}).exports,n),n.exports);var sn=ti((tt,ro)=>{var an={to(r,n){if(!n)return`\x1B[${r+1}G`;return`\x1B[${n+1};${r+1}H`},move(r,n){let o="";if(r<0)o+=`\x1B[${-r}D`;else if(r>0)o+=`\x1B[${r}C`;if(n<0)o+=`\x1B[${-n}A`;else if(n>0)o+=`\x1B[${n}B`;return o},up:(r=1)=>`\x1B[${r}A`,down:(r=1)=>`\x1B[${r}B`,forward:(r=1)=>`\x1B[${r}C`,backward:(r=1)=>`\x1B[${r}D`,nextLine:(r=1)=>"\x1B[E".repeat(r),prevLine:(r=1)=>"\x1B[F".repeat(r),left:"\x1B[G",hide:"\x1B[?25l",show:"\x1B[?25h",save:"\x1B7",restore:"\x1B8"},wi={up:(r=1)=>"\x1B[S".repeat(r),down:(r=1)=>"\x1B[T".repeat(r)},$i={screen:"\x1B[2J",up:(r=1)=>"\x1B[1J".repeat(r),down:(r=1)=>"\x1B[J".repeat(r),line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",lines(r){let n="";for(let o=0;o<r;o++)n+=this.line+(o<r-1?an.up():"");if(r)n+=an.left;return n}};ro.exports={cursor:an,scroll:wi,erase:$i,beep:"\x07"}});class X extends Error{constructor(r="Operation cancelled"){super(r)}}class v extends Error{hint;constructor(r,n){super(r);this.hint=n}}import{styleText as jr}from"util";import{stdout as un,stdin as eo}from"process";import*as or from"readline";import Pi from"readline";var Jn=(()=>{let r=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return(n)=>{let o=0;r.lastIndex=0;while(r.test(n))o+=1;return n.length-o}})(),An=(r)=>{return r===12288||r>=65281&&r<=65376||r>=65504&&r<=65510},Kn=(r)=>{return r===8987||r===9001||r>=12272&&r<=12287||r>=12289&&r<=12350||r>=12441&&r<=12543||r>=12549&&r<=12591||r>=12593&&r<=12686||r>=12688&&r<=12771||r>=12783&&r<=12830||r>=12832&&r<=12871||r>=12880&&r<=19903||r>=65040&&r<=65049||r>=65072&&r<=65106||r>=65108&&r<=65126||r>=65128&&r<=65131||r>=127488&&r<=127490||r>=127504&&r<=127547||r>=127552&&r<=127560||r>=131072&&r<=196605||r>=196608&&r<=262141};var ai=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,si=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,Yn=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,ci=/\t{1,1000}/y,Zn=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu,fi=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,mi=/\p{M}+/gu,ui={limit:1/0,ellipsis:""},xn=(r,n={},o={})=>{let i=n.limit??1/0,e=n.ellipsis??"",t=n?.ellipsisWidth??(e?xn(e,ui,o).width:0),a=0,s=o.controlWidth??0,c=o.tabWidth??8,f=o.emojiWidth??2,d=2,g=o.regularWidth??1,u=o.wideWidth??2,h=[[fi,g],[ai,0],[si,s],[ci,c],[Zn,f],[Yn,u]],l=0,b=0,k=r.length,R=0,C=!1,N=k,j=Math.max(0,i-t),F=0,E=0,M=0,L=0;r:while(!0){if(E>F||b>=k&&b>l){let H=r.slice(F,E)||r.slice(l,b);R=0;for(let V of H.replaceAll(mi,"")){let A=V.codePointAt(0)||0;if(An(A))L=2;else if(Kn(A))L=u;else L=g;if(M+L>j)N=Math.min(N,Math.max(F,l)+R);if(M+L>i){C=!0;break r}R+=V.length,M+=L}F=E=0}if(b>=k)break r;for(let H=0,V=h.length;H<V;H++){let[A,kr]=h[H];if(A.lastIndex=b,A.test(r)){if(R=A===Yn?Jn(r.slice(b,A.lastIndex)):A===Zn?1:A.lastIndex-b,L=R*kr,M+L>j)N=Math.min(N,b+Math.floor((j-M)/kr));if(M+L>i){C=!0;break r}M+=L,F=l,E=b,b=l=A.lastIndex;continue r}}b+=1}return{width:C?j:M,index:C?N:k,truncated:C,ellipsed:C&&i>=t}},Qn=xn;var pi={limit:1/0,ellipsis:"",ellipsisWidth:0},li=(r,n={})=>{return Qn(r,pi,n).width},K=li;var Lr="\x1B",Bn="\x9B",di=39,en="\x07",_n="[",gi="]",Tn="m",tn=`${gi}8;;`,Xn=new RegExp(`(?:\\${_n}(?<code>\\d+)m|\\${tn}(?<uri>.*)${en})`,"y"),Vn=(r)=>{if(r>=30&&r<=37)return 39;if(r>=90&&r<=97)return 39;if(r>=40&&r<=47)return 49;if(r>=100&&r<=107)return 49;if(r===1||r===2)return 22;if(r===3)return 23;if(r===4)return 24;if(r===7)return 27;if(r===8)return 28;if(r===9)return 29;if(r===0)return 0;return},On=(r)=>`${Lr}${_n}${r}${Tn}`,Sn=(r)=>`${Lr}${tn}${r}${en}`,on=(r,n,o)=>{let i=n[Symbol.iterator](),e=!1,t=!1,a=r.at(-1),s=a===void 0?0:K(a),c=i.next(),f=i.next(),d=0;while(!c.done){let g=c.value,u=K(g);if(s+u<=o)r[r.length-1]+=g;else r.push(g),s=0;if(g===Lr||g===Bn)e=!0,t=n.startsWith(tn,d+1);if(e){if(t){if(g===en)e=!1,t=!1}else if(g===Tn)e=!1}else if(s+=u,s===o&&!f.done)r.push(""),s=0;c=f,f=i.next(),d+=g.length}if(a=r.at(-1),!s&&a!==void 0&&a.length&&r.length>1)r[r.length-2]+=r.pop()},hi=(r)=>{let n=r.split(" "),o=n.length;while(o){if(K(n[o-1]))break;o--}if(o===n.length)return r;return n.slice(0,o).join(" ")+n.slice(o).join("")},bi=(r,n,o={})=>{if(o.trim!==!1&&r.trim()==="")return"";let i="",e,t,a=r.split(" "),s=[""],c=0;for(let g=0;g<a.length;g++){let u=a[g];if(o.trim!==!1){let l=s.at(-1)??"",b=l.trimStart();if(l.length!==b.length)s[s.length-1]=b,c=K(b)}if(g!==0){if(c>=n&&(o.wordWrap===!1||o.trim===!1))s.push(""),c=0;if(c||o.trim===!1)s[s.length-1]+=" ",c++}let h=K(u);if(o.hard&&h>n){let l=n-c,b=1+Math.floor((h-l-1)/n);if(Math.floor((h-1)/n)<b)s.push("");on(s,u,n),c=K(s.at(-1)??"");continue}if(c+h>n&&c&&h){if(o.wordWrap===!1&&c<n){on(s,u,n),c=K(s.at(-1)??"");continue}s.push(""),c=0}if(c+h>n&&o.wordWrap===!1){on(s,u,n),c=K(s.at(-1)??"");continue}s[s.length-1]+=u,c+=h}if(o.trim!==!1)s=s.map((g)=>hi(g));let f=s.join(`
|
|
4
|
+
`),d=!1;for(let g=0;g<f.length;g++){let u=f[g];if(i+=u,!d){if(d=u>="\uD800"&&u<="\uDBFF",d)continue}else d=!1;if(u===Lr||u===Bn){Xn.lastIndex=g+1;let l=Xn.exec(f)?.groups;if(l?.code!==void 0){let b=Number.parseFloat(l.code);e=b===di?void 0:b}else if(l?.uri!==void 0)t=l.uri.length===0?void 0:l.uri}if(f[g+1]===`
|
|
5
|
+
`){if(t)i+=Sn("");let h=e?Vn(e):void 0;if(e&&h)i+=On(h)}else if(u===`
|
|
6
|
+
`){if(e&&Vn(e))i+=On(e);if(t)i+=Sn(t)}}return i},vi=/\r?\n/;function O(r,n,o){return String(r).normalize().split(vi).map((i)=>bi(i,n,o)).join(`
|
|
7
|
+
`)}var W=Wn(sn(),1);import{ReadStream as no}from"tty";function _(r,n,o){if(!o.some((a)=>!a.disabled))return r;let i=r+n,e=Math.max(o.length-1,0),t=i<0?e:i>e?0:i;return o[t]?.disabled?_(t,n<0?-1:1,o):t}function Ir(r,n,o,i){let e=i.split(`
|
|
8
|
+
`),t=0,a=r;for(let c of e){if(a<=c.length)break;a-=c.length+1,t++}for(t=Math.max(0,Math.min(e.length-1,t+o)),a=Math.min(a,e[t].length)+n;a<0&&t>0;)t--,a+=e[t].length+1;for(;a>e[t].length&&t<e.length-1;)a-=e[t].length+1,t++;a=Math.max(0,Math.min(e[t].length,a));let s=0;for(let c=0;c<t;c++)s+=e[c].length+1;return s+a}var Ci=["up","down","left","right","space","enter","cancel"],Fi=["January","February","March","April","May","June","July","August","September","October","November","December"],q={actions:new Set(Ci),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"},withGuide:!0,date:{monthNames:[...Fi],messages:{required:"Please enter a valid date",invalidMonth:"There are only 12 months in a year",invalidDay:(r,n)=>`There are only ${r} days in ${n}`,afterMin:(r)=>`Date must be on or after ${r.toISOString().slice(0,10)}`,beforeMax:(r)=>`Date must be on or before ${r.toISOString().slice(0,10)}`}}};function pn(r,n){if(typeof r=="string")return q.aliases.get(r)===n;for(let o of r)if(o!==void 0&&pn(o,n))return!0;return!1}function ki(r,n){if(r===n)return;let o=r.split(`
|
|
9
|
+
`),i=n.split(`
|
|
10
|
+
`),e=Math.max(o.length,i.length),t=[];for(let a=0;a<e;a++)o[a]!==i[a]&&t.push(a);return{lines:t,numLinesBefore:o.length,numLinesAfter:i.length,numLines:e}}var yi=globalThis.process.platform.startsWith("win"),fn=Symbol("clack:cancel");function lr(r){return r===fn}function Dr(r,n){let o=r;o.isTTY&&o.setRawMode(n)}function to({input:r=eo,output:n=un,overwrite:o=!0,hideCursor:i=!0}={}){let e=or.createInterface({input:r,output:n,prompt:"",tabSize:1});or.emitKeypressEvents(r,e),r instanceof no&&r.isTTY&&r.setRawMode(!0);let t=(a,{name:s,sequence:c})=>{let f=String(a);if(pn([f,s,c],"cancel")){i&&n.write(W.cursor.show),process.exit(0);return}if(!o)return;or.moveCursor(n,s==="return"?0:-1,s==="return"?-1:0,()=>{or.clearLine(n,1,()=>{r.once("keypress",t)})})};return i&&n.write(W.cursor.hide),r.once("keypress",t),()=>{r.off("keypress",t),i&&n.write(W.cursor.show),r instanceof no&&r.isTTY&&!yi&&r.setRawMode(!1),e.terminal=!1,e.close()}}var dr=(r)=>("columns"in r)&&typeof r.columns=="number"?r.columns:80,ln=(r)=>("rows"in r)&&typeof r.rows=="number"?r.rows:20;function ir(r,n,o,i=o,e=o,t){let a=dr(r??un);return O(n,a-o.length,{hard:!0,trim:!1}).split(`
|
|
11
|
+
`).map((s,c,f)=>{let d=t?t(s,c):s;return c===0?`${i}${d}`:c===f.length-1?`${e}${d}`:`${o}${d}`}).join(`
|
|
12
|
+
`)}function ao(r,n){if("~standard"in r){let o=r["~standard"].validate(n);if(o instanceof Promise)throw TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");return o.issues?.at(0)?.message}return r(n)}class T{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame="";_subscribers=new Map;_cursor=0;state="initial";error="";value;userInput="";constructor(r,n=!0){let{input:o=eo,output:i=un,render:e,signal:t,...a}=r;this.opts=a,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=e.bind(this),this._track=n,this._abortSignal=t,this.input=o,this.output=i}unsubscribe(){this._subscribers.clear()}setSubscriber(r,n){let o=this._subscribers.get(r)??[];o.push(n),this._subscribers.set(r,o)}on(r,n){this.setSubscriber(r,{cb:n})}once(r,n){this.setSubscriber(r,{cb:n,once:!0})}emit(r,...n){let o=this._subscribers.get(r)??[],i=[];for(let e of o)e.cb(...n),e.once&&i.push(()=>o.splice(o.indexOf(e),1));for(let e of i)e()}prompt(){return new Promise((r)=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),r(fn);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}this.rl=Pi.createInterface({input:this.input,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on("keypress",this.onKeypress),Dr(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(W.cursor.show),this.output.off("resize",this.render),Dr(this.input,!1),r(this.value)}),this.once("cancel",()=>{this.output.write(W.cursor.show),this.output.off("resize",this.render),Dr(this.input,!1),r(fn)})})}_isActionKey(r,n){return r==="\t"}_shouldSubmit(r,n){return!0}_setValue(r){this.value=r,this.emit("value",this.value)}_setUserInput(r,n){this.userInput=r??"",this.emit("userInput",this.userInput),n&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:"u"}),this._setUserInput("")}onKeypress(r,n){if(this._track&&n.name!=="return"&&(n.name&&this._isActionKey(r,n)&&this.rl?.write(null,{ctrl:!0,name:"h"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state==="error"&&(this.state="active"),n?.name&&(!this._track&&q.aliases.has(n.name)&&this.emit("cursor",q.aliases.get(n.name)),q.actions.has(n.name)&&this.emit("cursor",n.name)),r&&(r.toLowerCase()==="y"||r.toLowerCase()==="n")&&this.emit("confirm",r.toLowerCase()==="y"),this.emit("key",r,n),n?.name==="return"&&this._shouldSubmit(r,n)){if(this.opts.validate){let o=ao(this.opts.validate,this.value);o&&(this.error=o instanceof Error?o.message:o,this.state="error",this.rl?.write(this.userInput))}this.state!=="error"&&(this.state="submit")}pn([r,n?.name,n?.sequence],"cancel")&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close()}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
|
|
13
|
+
`),Dr(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let r=O(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`
|
|
14
|
+
`).length-1;this.output.write(W.cursor.move(-999,r*-1))}render(){let r=O(this._render(this)??"",process.stdout.columns,{hard:!0,trim:!1});if(r!==this._prevFrame){if(this.state==="initial")this.output.write(W.cursor.hide);else{let n=ki(this._prevFrame,r),o=ln(this.output);if(this.restoreCursor(),n){let i=Math.max(0,n.numLinesAfter-o),e=Math.max(0,n.numLinesBefore-o),t=n.lines.find((a)=>a>=i);if(t===void 0){this._prevFrame=r;return}if(n.lines.length===1){this.output.write(W.cursor.move(0,t-e)),this.output.write(W.erase.lines(1));let a=r.split(`
|
|
15
|
+
`);this.output.write(a[t]),this._prevFrame=r,this.output.write(W.cursor.move(0,a.length-t-1));return}else if(n.lines.length>1){if(i<e)t=i;else{let s=t-e;s>0&&this.output.write(W.cursor.move(0,s))}this.output.write(W.erase.down());let a=r.split(`
|
|
16
|
+
`).slice(t);this.output.write(a.join(`
|
|
17
|
+
`)),this._prevFrame=r;return}}this.output.write(W.erase.down())}this.output.write(r),this.state==="initial"&&(this.state="active"),this._prevFrame=r}}}function Li(r,n){if(r===void 0||n.length===0)return 0;let o=n.findIndex((i)=>i.value===r);return o!==-1?o:0}function Ii(r,n){return(n.label??String(n.value)).toLowerCase().includes(r.toLowerCase())}function Di(r,n){if(n)return r?n:n[0]}var Ri=class extends T{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#n=0;#e="";#r;#t;#s;get cursor(){return this.#n}get userInputWithCursor(){if(!this.userInput)return jr(["inverse","hidden"],"_");if(this._cursor>=this.userInput.length)return`${this.userInput}\u2588`;let n=this.userInput.slice(0,this.cursor),o=this.userInput.slice(this.cursor,this.cursor+1),i=this.userInput.slice(this.cursor+1);return`${n}${jr("inverse",o)}${i}`}get options(){return typeof this.#t=="function"?this.#t():this.#t}constructor(n){super(n),this.#t=n.options,this.#s=n.placeholder;let o=this.options;this.filteredOptions=[...o],this.multiple=n.multiple===!0,this.#r=typeof n.options=="function"?n.filter:n.filter??Ii;let i;if(n.initialValue&&Array.isArray(n.initialValue)?this.multiple?i=n.initialValue:i=n.initialValue.slice(0,1):!this.multiple&&this.options.length>0&&(i=[this.options[0]?.value]),i)for(let e of i){let t=o.findIndex((a)=>a.value===e);t!==-1&&(this.toggleSelected(e),this.#n=t)}this.focusedValue=this.options[this.#n]?.value,this.on("key",(e,t)=>this.#o(e,t)),this.on("userInput",(e)=>this.#i(e))}_isActionKey(n,o){return n==="\t"||this.multiple&&this.isNavigating&&o.name==="space"&&n!==void 0&&n!==""}#o(n,o){let i=o.name==="up",e=o.name==="down",t=o.name==="return",a=this.userInput===""||this.userInput==="\t",s=this.#s,c=this.options,f=s!==void 0&&s!==""&&c.some((d)=>!d.disabled&&(this.#r?this.#r(s,d):!0));if(o.name==="tab"&&a&&f){this.userInput==="\t"&&this._clearUserInput(),this._setUserInput(s,!0),this.isNavigating=!1;return}i||e?(this.#n=_(this.#n,i?-1:1,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#n]?.value,this.multiple||(this.selectedValues=[this.focusedValue]),this.isNavigating=!0):t?this.value=Di(this.multiple,this.selectedValues):this.multiple?this.focusedValue!==void 0&&(o.name==="tab"||this.isNavigating&&o.name==="space")?this.toggleSelected(this.focusedValue):this.isNavigating=!1:(this.focusedValue&&(this.selectedValues=[this.focusedValue]),this.isNavigating=!1)}deselectAll(){this.selectedValues=[]}toggleSelected(n){this.filteredOptions.length!==0&&(this.multiple?this.selectedValues.includes(n)?this.selectedValues=this.selectedValues.filter((o)=>o!==n):this.selectedValues=[...this.selectedValues,n]:this.selectedValues=[n])}#i(n){if(n!==this.#e){this.#e=n;let o=this.options;n&&this.#r?this.filteredOptions=o.filter((t)=>this.#r?.(n,t)):this.filteredOptions=[...o];let i=Li(this.focusedValue,this.filteredOptions);this.#n=_(i,0,this.filteredOptions);let e=this.filteredOptions[this.#n];e&&!e.disabled?this.focusedValue=e.value:this.focusedValue=void 0,this.multiple||(this.focusedValue!==void 0?this.toggleSelected(this.focusedValue):this.deselectAll())}}};class dn extends T{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(r){super(r,!1),this.value=!!r.initialValue,this.on("userInput",()=>{this.value=this._value}),this.on("confirm",(n)=>{this.output.write(W.cursor.move(0,-1)),this.value=n,this.state="submit",this.close()}),this.on("cursor",()=>{this.value=!this.value})}}var ji={Y:{type:"year",len:4},M:{type:"month",len:2},D:{type:"day",len:2}};function oo(r){return[...r].map((n)=>ji[n])}function Mi(r){let n=new Intl.DateTimeFormat(r,{year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(new Date(2000,0,15)),o=[],i="/";for(let e of n)e.type==="literal"?i=e.value.trim()||e.value:(e.type==="year"||e.type==="month"||e.type==="day")&&o.push({type:e.type,len:e.type==="year"?4:2});return{segments:o,separator:i}}function cn(r){return Number.parseInt((r||"0").replace(/_/g,"0"),10)||0}function Rr(r){return{year:cn(r.year),month:cn(r.month),day:cn(r.day)}}function mn(r,n){return new Date(r||2001,n||1,0).getDate()}function so(r){let{year:n,month:o,day:i}=Rr(r);if(!n||n<0||n>9999||!o||o<1||o>12||!i||i<1)return;let e=new Date(Date.UTC(n,o-1,i));if(!(e.getUTCFullYear()!==n||e.getUTCMonth()!==o-1||e.getUTCDate()!==i))return{year:n,month:o,day:i}}function io(r){let n=so(r);return n?new Date(Date.UTC(n.year,n.month-1,n.day)):void 0}function Ui(r,n,o,i){let e=o?{year:o.getUTCFullYear(),month:o.getUTCMonth()+1,day:o.getUTCDate()}:null,t=i?{year:i.getUTCFullYear(),month:i.getUTCMonth()+1,day:i.getUTCDate()}:null;return r==="year"?{min:e?.year??1,max:t?.year??9999}:r==="month"?{min:e&&n.year===e.year?e.month:1,max:t&&n.year===t.year?t.month:12}:{min:e&&n.year===e.year&&n.month===e.month?e.day:1,max:t&&n.year===t.year&&n.month===t.month?t.day:mn(n.year,n.month)}}class co extends T{#n;#e;#r;#t;#s;#o={segmentIndex:0,positionInSegment:0};#i=!0;#a=null;inlineError="";get segmentCursor(){return{...this.#o}}get segmentValues(){return{...this.#r}}get segments(){return this.#n}get separator(){return this.#e}get formattedValue(){return this.#u(this.#r)}#u(r){return this.#n.map((n)=>r[n.type]).join(this.#e)}#c(){this._setUserInput(this.#u(this.#r)),this._setValue(io(this.#r)??void 0)}constructor(r){let n=r.format?{segments:oo(r.format),separator:r.separator??"/"}:Mi(r.locale),o=r.separator??n.separator,i=r.format?oo(r.format):n.segments,e=r.initialValue??r.defaultValue,t=e?{year:String(e.getUTCFullYear()).padStart(4,"0"),month:String(e.getUTCMonth()+1).padStart(2,"0"),day:String(e.getUTCDate()).padStart(2,"0")}:{year:"____",month:"__",day:"__"},a=i.map((s)=>t[s.type]).join(o);super({...r,initialUserInput:a},!1),this.#n=i,this.#e=o,this.#r=t,this.#t=r.minDate,this.#s=r.maxDate,this.#c(),this.on("cursor",(s)=>this.#d(s)),this.on("key",(s,c)=>this.#g(s,c)),this.on("finalize",()=>this.#h(r))}#f(){let r=Math.max(0,Math.min(this.#o.segmentIndex,this.#n.length-1)),n=this.#n[r];if(n)return this.#o.positionInSegment=Math.max(0,Math.min(this.#o.positionInSegment,n.len-1)),{segment:n,index:r}}#m(r){this.inlineError="",this.#a=null;let n=this.#f();n&&(this.#o.segmentIndex=Math.max(0,Math.min(this.#n.length-1,n.index+r)),this.#o.positionInSegment=0,this.#i=!0)}#p(r){let n=this.#f();if(!n)return;let{segment:o}=n,i=this.#r[o.type],e=!i||i.replace(/_/g,"")==="",t=Number.parseInt((i||"0").replace(/_/g,"0"),10)||0,a=Ui(o.type,Rr(this.#r),this.#t,this.#s),s;e?s=r===1?a.min:a.max:s=Math.max(Math.min(a.max,t+r),a.min),this.#r={...this.#r,[o.type]:s.toString().padStart(o.len,"0")},this.#i=!0,this.#a=null,this.#c()}#d(r){if(r)switch(r){case"right":return this.#m(1);case"left":return this.#m(-1);case"up":return this.#p(1);case"down":return this.#p(-1)}}#g(r,n){if(n?.name==="backspace"||n?.sequence==="\x7F"||n?.sequence==="\b"||r==="\x7F"||r==="\b"){this.inlineError="";let o=this.#f();if(!o)return;if(!this.#r[o.segment.type].replace(/_/g,"")){this.#m(-1);return}this.#r[o.segment.type]="_".repeat(o.segment.len),this.#i=!0,this.#o.positionInSegment=0,this.#c();return}if(n?.name==="tab"){this.inlineError="";let o=this.#f();if(!o)return;let i=n.shift?-1:1,e=o.index+i;e>=0&&e<this.#n.length&&(this.#o.segmentIndex=e,this.#o.positionInSegment=0,this.#i=!0);return}if(r&&/^[0-9]$/.test(r)){let o=this.#f();if(!o)return;let{segment:i}=o,e=!this.#r[i.type].replace(/_/g,"");if(this.#i&&this.#a!==null&&!e){let u=this.#a+r,h={...this.#r,[i.type]:u},l=this.#l(h,i);if(l){this.inlineError=l,this.#a=null,this.#i=!1;return}this.inlineError="",this.#r[i.type]=u,this.#a=null,this.#i=!1,this.#c(),o.index<this.#n.length-1&&(this.#o.segmentIndex=o.index+1,this.#o.positionInSegment=0,this.#i=!0);return}this.#i&&!e&&(this.#r[i.type]="_".repeat(i.len),this.#o.positionInSegment=0),this.#i=!1,this.#a=null;let t=this.#r[i.type],a=t.indexOf("_"),s=a>=0?a:Math.min(this.#o.positionInSegment,i.len-1);if(s<0||s>=i.len)return;let c=t.slice(0,s)+r+t.slice(s+1),f=!1;if(s===0&&t==="__"&&(i.type==="month"||i.type==="day")){let u=Number.parseInt(r,10);c=`0${r}`,f=u<=(i.type==="month"?1:2)}if(i.type==="year"&&(c=(t.replace(/_/g,"")+r).padStart(i.len,"_")),!c.includes("_")){let u={...this.#r,[i.type]:c},h=this.#l(u,i);if(h){this.inlineError=h;return}}this.inlineError="",this.#r[i.type]=c;let d=c.includes("_")?void 0:so(this.#r);if(d){let{year:u,month:h}=d,l=mn(u,h);this.#r={year:String(Math.max(0,Math.min(9999,u))).padStart(4,"0"),month:String(Math.max(1,Math.min(12,h))).padStart(2,"0"),day:String(Math.max(1,Math.min(l,d.day))).padStart(2,"0")}}this.#c();let g=c.indexOf("_");f?(this.#i=!0,this.#a=r):g>=0?this.#o.positionInSegment=g:a>=0&&o.index<this.#n.length-1?(this.#o.segmentIndex=o.index+1,this.#o.positionInSegment=0,this.#i=!0):this.#o.positionInSegment=Math.min(s+1,i.len-1)}}#l(r,n){let{month:o,day:i}=Rr(r);if(n.type==="month"&&(o<0||o>12))return q.date.messages.invalidMonth;if(n.type==="day"&&(i<0||i>31))return q.date.messages.invalidDay(31,"any month")}#h(r){let{year:n,month:o,day:i}=Rr(this.#r);if(n&&o&&i){let e=mn(n,o);this.#r={...this.#r,day:String(Math.min(i,e)).padStart(2,"0")}}this.value=io(this.#r)??r.defaultValue??void 0}}var Hi=class extends T{options;cursor=0;#n;getGroupItems(n){return this.options.filter((o)=>o.group===n)}isGroupSelected(n){let o=this.getGroupItems(n),i=this.value;return i===void 0?!1:o.every((e)=>i.includes(e.value))}toggleValue(){let n=this.options[this.cursor];if(n!==void 0)if(this.value===void 0&&(this.value=[]),n.group===!0){let o=n.value,i=this.getGroupItems(o);this.isGroupSelected(o)?this.value=this.value.filter((e)=>i.findIndex((t)=>t.value===e)===-1):this.value=[...this.value,...i.map((e)=>e.value)],this.value=Array.from(new Set(this.value))}else{let o=this.value.includes(n.value);this.value=o?this.value.filter((i)=>i!==n.value):[...this.value,n.value]}}constructor(n){super(n,!1);let{options:o}=n;this.#n=n.selectableGroups!==!1,this.options=Object.entries(o).flatMap(([i,e])=>[{value:i,group:!0,label:i},...e.map((t)=>({...t,group:i}))]),this.value=[...n.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:i})=>i===n.cursorAt),this.#n?0:1),this.on("cursor",(i)=>{switch(i){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let e=this.options[this.cursor]?.group===!0;!this.#n&&e&&(this.cursor=this.cursor===0?this.options.length-1:this.cursor-1);break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let e=this.options[this.cursor]?.group===!0;!this.#n&&e&&(this.cursor=this.cursor===this.options.length-1?0:this.cursor+1);break}case"space":this.toggleValue();break}})}},Ei=new Set(["up","down","left","right"]);class fo extends T{#n=!1;#e;focused="editor";get userInputWithCursor(){if(this.state==="submit")return this.userInput;let r=this.userInput;if(this.cursor>=r.length)return`${r}\u2588`;let n=r.slice(0,this.cursor),o=r.slice(this.cursor,this.cursor+1),i=r.slice(this.cursor+1);return o===`
|
|
18
|
+
`?`${n}\u2588
|
|
19
|
+
${i}`:`${n}${jr("inverse",o)}${i}`}get cursor(){return this._cursor}#r(r){if(this.userInput.length===0){this._setUserInput(r);return}this._setUserInput(this.userInput.slice(0,this.cursor)+r+this.userInput.slice(this.cursor))}#t(r){let n=this.value??"";switch(r){case"up":this._cursor=Ir(this._cursor,0,-1,n);return;case"down":this._cursor=Ir(this._cursor,0,1,n);return;case"left":this._cursor=Ir(this._cursor,-1,0,n);return;case"right":this._cursor=Ir(this._cursor,1,0,n);return}}_shouldSubmit(r,n){if(this.#e)return this.focused==="submit"?!0:(this.#r(`
|
|
20
|
+
`),this._cursor++,!1);let o=this.#n;return this.#n=!0,o&&this.cursor===this.userInput.length?(this.userInput[this.cursor-1]===`
|
|
21
|
+
`&&(this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--),!0):(this.#r(`
|
|
22
|
+
`),this._cursor++,!1)}constructor(r){let n=r.initialUserInput??r.initialValue;super({...r,initialUserInput:n},!1),n!==void 0&&(this._cursor=n.length),this.#e=r.showSubmit??!1,this.on("key",(o,i)=>{if(i?.name&&Ei.has(i.name)){this.#n=!1,this.#t(i.name);return}if(o==="\t"&&this.#e){this.focused=this.focused==="editor"?"submit":"editor";return}if(i?.name!=="return"){if(this.#n=!1,i?.name==="backspace"&&this.cursor>0){this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--;return}if(i?.name==="delete"&&this.cursor<this.userInput.length){this._setUserInput(this.userInput.slice(0,this.cursor)+this.userInput.slice(this.cursor+1));return}o&&(this.#e&&this.focused==="submit"&&(this.focused="editor"),this.#r(o??""),this._cursor++)}}),this.on("userInput",(o)=>{this._setValue(o)}),this.on("finalize",()=>{this.value||(this.value=r.defaultValue),this.value===void 0&&(this.value="")})}}class gn extends T{options;cursor=0;get _value(){return this.options[this.cursor]?.value}get _enabledOptions(){return this.options.filter((r)=>r.disabled!==!0)}toggleAll(){let r=this._enabledOptions,n=this.value!==void 0&&this.value.length===r.length;this.value=n?[]:r.map((o)=>o.value)}toggleInvert(){let r=this.value;if(!r)return;let n=this._enabledOptions.filter((o)=>!r.includes(o.value));this.value=n.map((o)=>o.value)}toggleValue(){this.value===void 0&&(this.value=[]);let r=this.value.includes(this._value);this.value=r?this.value.filter((n)=>n!==this._value):[...this.value,this._value]}constructor(r){super(r,!1),this.options=r.options,this.value=[...r.initialValues??[]];let n=Math.max(this.options.findIndex(({value:o})=>o===r.cursorAt),0);this.cursor=this.options[n]?.disabled?_(n,1,this.options):n,this.on("key",(o,i)=>{i.name==="a"&&this.toggleAll(),i.name==="i"&&this.toggleInvert()}),this.on("cursor",(o)=>{switch(o){case"left":case"up":this.cursor=_(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=_(this.cursor,1,this.options);break;case"space":this.toggleValue();break}})}}var mo=class extends T{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){let n=this._selectedValue;this.value=n===void 0?void 0:n.value}constructor(n){super(n,!1),this.options=n.options;let o=this.options.findIndex(({value:e})=>e===n.initialValue),i=o===-1?0:o;this.cursor=this.options[i]?.disabled?_(i,1,this.options):i,this.changeValue(),this.on("cursor",(e)=>{switch(e){case"left":case"up":this.cursor=_(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=_(this.cursor,1,this.options);break}this.changeValue()})}};class hn extends T{get userInputWithCursor(){if(this.state==="submit")return this.userInput;let r=this.userInput;if(this.cursor>=r.length)return`${this.userInput}\u2588`;let n=r.slice(0,this.cursor),o=r.slice(this.cursor,this.cursor+1),i=r.slice(this.cursor+1);return`${n}${jr("inverse",o)}${i}`}get cursor(){return this._cursor}constructor(r){super({...r,initialUserInput:r.initialUserInput??r.initialValue}),this.on("userInput",(n)=>{this._setValue(n)}),this.on("finalize",()=>{this.value||(this.value=r.defaultValue),this.value===void 0&&(this.value="")})}}import{styleText as m,stripVTControlCharacters as bt}from"util";import x from"process";var hr=Wn(sn(),1);function Ni(){if(x.platform!=="win32")return x.env.TERM!=="linux";return Boolean(x.env.CI)||Boolean(x.env.WT_SESSION)||Boolean(x.env.TERMINUS_SUBLIME)||x.env.ConEmuTask==="{cmd::Cmder}"||x.env.TERM_PROGRAM==="Terminus-Sublime"||x.env.TERM_PROGRAM==="vscode"||x.env.TERM==="xterm-256color"||x.env.TERM==="alacritty"||x.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var bn=Ni(),qi=()=>process.env.CI==="true";var y=(r,n)=>bn?r:n,Gi=y("\u25C6","*"),ho=y("\u25A0","x"),bo=y("\u25B2","x"),Hr=y("\u25C7","o"),zi=y("\u250C","T"),P=y("\u2502","|"),er=y("\u2514","\u2014"),Pt=y("\u2510","T"),Ct=y("\u2518","\u2014"),vn=y("\u25CF",">"),Ur=y("\u25CB"," "),Wi=y("\u25FB","[\u2022]"),uo=y("\u25FC","[+]"),po=y("\u25FB","[ ]"),Ft=y("\u25AA","\u2022"),lo=y("\u2500","-"),Ji=y("\u256E","+"),Ai=y("\u251C","+"),Ki=y("\u256F","+"),Yi=y("\u2570","+"),kt=y("\u256D","+"),Zi=y("\u25CF","\u2022"),xi=y("\u25C6","*"),Qi=y("\u25B2","!"),Xi=y("\u25A0","x"),Er=(r)=>{switch(r){case"initial":case"active":return m("cyan",Gi);case"cancel":return m("red",ho);case"error":return m("yellow",bo);case"submit":return m("green",Hr)}},vo=(r)=>{switch(r){case"initial":case"active":return m("cyan",P);case"cancel":return m("red",P);case"error":return m("yellow",P);case"submit":return m("green",P)}};function wo(r,n){let o=[`${n?`${m("cyan",P)} `:""}${r.join(" \u2022 ")}`];return n&&o.push(m("cyan",er)),o}var go=(r,n,o,i,e,t=!1)=>{let a=n,s=0;if(t)for(let c=i-1;c>=o;c--){let f=r[c];if(f&&(a-=f.length),s++,a<=e)break}else for(let c=o;c<i;c++){let f=r[c];if(f&&(a-=f.length),s++,a<=e)break}return{lineCount:a,removals:s}},wn=({cursor:r,options:n,style:o,output:i=process.stdout,maxItems:e=Number.POSITIVE_INFINITY,columnPadding:t=0,rowPadding:a=4})=>{let s=dr(i)-t,c=ln(i),f=m("dim","..."),d=Math.max(c-a,0),g=Math.max(Math.min(e,d),5),u=0;r>=g-3&&(u=Math.max(Math.min(r-g+3,n.length-g),0));let h=g<n.length&&u>0,l=g<n.length&&u+g<n.length,b=Math.min(u+g,n.length),k=[],R=0;h&&R++,l&&R++;let C=u+(h?1:0),N=b-(l?1:0);for(let F=C;F<N;F++){let E=n[F],M=E?o(E,F===r):"",L=O(M,s,{hard:!0,trim:!1}).split(`
|
|
23
|
+
`);k.push(L),R+=L.length}if(R>d){let F=0,E=0,M=R,L=r-C,H=d,V=()=>go(k,M,0,L,H),A=()=>go(k,M,L+1,k.length,H,!0);h?({lineCount:M,removals:F}=V(),M>H&&(l||(H-=1),{lineCount:M,removals:E}=A())):(l||(H-=1),{lineCount:M,removals:E}=A(),M>H&&(H-=1,{lineCount:M,removals:F}=V())),F>0&&(h=!0,k.splice(0,F)),E>0&&(l=!0,k.splice(k.length-E,E))}let j=[];h&&j.push(f);for(let F of k)for(let E of F)j.push(E);return l&&j.push(f),j};var $o=(r)=>{let n=r.active??"Yes",o=r.inactive??"No";return new dn({active:n,inactive:o,signal:r.signal,input:r.input,output:r.output,initialValue:r.initialValue??!0,render(){let i=r.withGuide??q.withGuide,e=`${Er(this.state)} `,t=i?`${m("gray",P)} `:"",a=ir(r.output,r.message,t,e),s=`${i?`${m("gray",P)}
|
|
24
|
+
`:""}${a}
|
|
25
|
+
`,c=this.value?n:o;switch(this.state){case"submit":{let f=i?`${m("gray",P)} `:"";return`${s}${f}${m("dim",c)}`}case"cancel":{let f=i?`${m("gray",P)} `:"";return`${s}${f}${m(["strikethrough","dim"],c)}${i?`
|
|
26
|
+
${m("gray",P)}`:""}`}default:{let f=i?`${m("cyan",P)} `:"",d=i?m("cyan",er):"";return`${s}${f}${this.value?`${m("green",vn)} ${n}`:`${m("dim",Ur)} ${m("dim",n)}`}${r.vertical?i?`
|
|
27
|
+
${m("cyan",P)} `:`
|
|
28
|
+
`:` ${m("dim","/")} `}${this.value?`${m("dim",Ur)} ${m("dim",o)}`:`${m("green",vn)} ${o}`}
|
|
29
|
+
${d}
|
|
30
|
+
`}}}}).prompt()};var Nr=async(r,n)=>{let o={},i=Object.keys(r);for(let e of i){let t=r[e],a=await t({results:o})?.catch((s)=>{throw s});if(typeof n?.onCancel=="function"&&lr(a)){o[e]="canceled",n.onCancel({results:o});continue}o[e]=a}return o},Vi=[`${m("dim","\u2191/\u2193")} to navigate`,`${m("dim","Space:")} select`,`${m("dim","Enter:")} confirm`],gr=(r,n)=>r.split(`
|
|
31
|
+
`).map((o)=>n(o)).join(`
|
|
32
|
+
`),Po=(r)=>{let n=(e,t)=>{let a=e.label??String(e.value);return t==="disabled"?`${m("gray",po)} ${gr(a,(s)=>m(["strikethrough","gray"],s))}${e.hint?` ${m("dim",`(${e.hint??"disabled"})`)}`:""}`:t==="active"?`${m("cyan",Wi)} ${a}${e.hint?` ${m("dim",`(${e.hint})`)}`:""}`:t==="selected"?`${m("green",uo)} ${gr(a,(s)=>m("dim",s))}${e.hint?` ${m("dim",`(${e.hint})`)}`:""}`:t==="cancelled"?`${gr(a,(s)=>m(["strikethrough","dim"],s))}`:t==="active-selected"?`${m("green",uo)} ${a}${e.hint?` ${m("dim",`(${e.hint})`)}`:""}`:t==="submitted"?`${gr(a,(s)=>m("dim",s))}`:`${m("dim",po)} ${gr(a,(s)=>m("dim",s))}`},o=r.required??!0,i=r.showInstructions??!0;return new gn({options:r.options,signal:r.signal,input:r.input,output:r.output,initialValues:r.initialValues,required:o,cursorAt:r.cursorAt,validate(e){if(o&&(e===void 0||e.length===0))return`Please select at least one option.
|
|
33
|
+
${m("reset",m("dim",`Press ${m(["gray","bgWhite","inverse"]," space ")} to select, ${m("gray",m("bgWhite",m("inverse"," enter ")))} to submit`))}`},render(){let e=r.withGuide??q.withGuide,t=ir(r.output,r.message,e?`${vo(this.state)} `:"",`${Er(this.state)} `),a=`${e?`${m("gray",P)}
|
|
34
|
+
`:""}${t}
|
|
35
|
+
`,s=this.value??[],c=(f,d)=>{if(f.disabled)return n(f,"disabled");let g=s.includes(f.value);return d&&g?n(f,"active-selected"):g?n(f,"selected"):n(f,d?"active":"inactive")};switch(this.state){case"submit":{let f=this.options.filter(({value:g})=>s.includes(g)).map((g)=>n(g,"submitted")).join(m("dim",", "))||m("dim","none"),d=ir(r.output,f,e?`${m("gray",P)} `:"");return`${a}${d}`}case"cancel":{let f=this.options.filter(({value:g})=>s.includes(g)).map((g)=>n(g,"cancelled")).join(m("dim",", "));if(f.trim()==="")return`${a}${m("gray",P)}`;let d=ir(r.output,f,e?`${m("gray",P)} `:"");return`${a}${d}${e?`
|
|
36
|
+
${m("gray",P)}`:""}`}case"error":{let f=e?`${m("yellow",P)} `:"",d=this.error.split(`
|
|
37
|
+
`).map((h,l)=>l===0?`${e?`${m("yellow",er)} `:""}${m("yellow",h)}`:` ${h}`).join(`
|
|
38
|
+
`),g=a.split(`
|
|
39
|
+
`).length,u=d.split(`
|
|
40
|
+
`).length+1;return`${a}${f}${wn({output:r.output,options:this.options,cursor:this.cursor,maxItems:r.maxItems,columnPadding:f.length,rowPadding:g+u,style:c}).join(`
|
|
41
|
+
${f}`)}
|
|
42
|
+
${d}
|
|
43
|
+
`}default:{let f=e?`${m("cyan",P)} `:"",d=a.split(`
|
|
44
|
+
`).length,g=i?wo(Vi,e):e?[m("cyan",er)]:[],u=g.join(`
|
|
45
|
+
`),h=g.length+1;return`${a}${f}${wn({output:r.output,options:this.options,cursor:this.cursor,maxItems:r.maxItems,columnPadding:f.length,rowPadding:d+h,style:c}).join(`
|
|
46
|
+
${f}`)}
|
|
47
|
+
${u}
|
|
48
|
+
`}}}}).prompt()};var w={message:(r=[],{symbol:n=m("gray",P),secondarySymbol:o=m("gray",P),output:i=process.stdout,spacing:e=1,withGuide:t}={})=>{let a=[],s=t??q.withGuide,c=s?o:"",f=s?`${n} `:"",d=s?`${o} `:"";for(let u=0;u<e;u++)a.push(c);let g=Array.isArray(r)?r:r.split(`
|
|
49
|
+
`);if(g.length>0){let[u,...h]=g;u.length>0?a.push(`${f}${u}`):a.push(s?n:"");for(let l of h)l.length>0?a.push(`${d}${l}`):a.push(s?o:"")}i.write(`${a.join(`
|
|
56
50
|
`)}
|
|
57
|
-
`)},info:(n
|
|
58
|
-
`)}
|
|
59
|
-
|
|
60
|
-
`,preHook:`export BUN_INSTALL_CACHE_DIR=./.bun/cache
|
|
61
|
-
`,runnerEnv:`ACTIONS_RUNNER_HOOK_JOB_STARTED=./hooks/pre.sh
|
|
62
|
-
ACTIONS_RUNNER_HOOK_JOB_COMPLETED=./hooks/post.sh
|
|
63
|
-
`}});var{$:xi}=globalThis.Bun;async function Ri({overwrite:n,numberOfMachines:r,directory:o,runnerBase:i}){let s=U({prefix:"createMachines:extract",secrets:[]}),c=Number(r),a=(()=>{try{let m=Bun.spawnSync(["nproc"]);return Number.parseInt(m.stdout.toString().trim(),10)||4}catch{try{let m=Bun.spawnSync(["sysctl","-n","hw.ncpu"]);return Number.parseInt(m.stdout.toString().trim(),10)||4}catch{return 4}}})(),u=Math.min(Math.max(2,Math.floor(a/2)),c,8);s.info(`Extracting ${c} runners with concurrency of ${u}`);let t=Array.from({length:c},(m,b)=>b+1).map((m)=>({execute:async()=>{let b=`${o}/machines/${m}`;if(await G.exists(b))if(n)s.debug(`Machine ${m} already exists, removing...`),await xi`rm -rf ${b}`;else{s.debug(`Machine ${m} already exists, skipping...`);return}await $n(b),await xi`tar xzf ${i} -C ${b.replace(`${o}/`,"")}`.cwd(o),await li(b),s.debug(`Machine ${m} extracted successfully`)},runnerIndex:m})),f=[];for(let m=0;m<t.length;m+=u){let b=t.slice(m,m+u),y=Math.floor(m/u)+1,e=Math.ceil(t.length/u);s.info(`Processing batch ${y}/${e} (${b.length} runners)`);let p=await Promise.allSettled(b.map((d)=>d.execute()));for(let d=0;d<p.length;d++){let x=p[d];if(x&&x.status==="rejected")throw s.error(`Failed to extract runner ${b[d]?.runnerIndex}: ${x.reason}`),x.reason}f.push(...p),s.info(`Batch ${y}/${e} completed successfully`)}s.info(`Successfully extracted ${c} runners`)}var $i=O(()=>{nn();pn();hi()});function yc(){if(Ei)return;Ei=!0;let n=()=>{if(sn.size>0)on.info("Cleaning up workers...");Xr()};process.on("exit",n),process.on("SIGINT",n),process.on("SIGTERM",n)}async function ei(n){yc();let r=new Worker(mc);return r.addEventListener("message",(o)=>{let{type:i,message:s}=o.data;if(i==="success")on.info(`[Worker ${n.index}] ${s}`);else if(i==="error")on.error(`[Worker ${n.index}] ${s}`);else if(i==="progress")on.debug(`[Worker ${n.index}] Progress: ${s}`)}),r.addEventListener("error",(o)=>{on.error(`[Worker ${n.index}] Error:`,o.message)}),r.addEventListener("exit",()=>{sn.delete(n.index),on.debug(`[Worker ${n.index}] Exited. Remaining: ${sn.size}`)}),sn.set(n.index,r),r.postMessage({data:n,timestamp:Date.now(),type:"init"}),on.debug(`Worker ${n.index} spawned. Total: ${sn.size}`),`worker-${n.index}`}function Xr(){if(sn.size>0){on.info(`Terminating ${sn.size} workers...`);for(let n of sn.values())try{n.terminate()}catch(r){on.error("Failed to terminate worker:",r)}sn.clear()}}var on,mc,sn,Ei=!1;var Ci=O(()=>{X();Fn();on=L({prefix:"WorkerManager"}),mc=new URL("../workers/runner-worker.ts",import.meta.url).href,sn=new Map});async function vn({directory:n,numberOfMachines:r,token:o,url:i,name:s,labels:c,runnerGroup:a}){let u=U({prefix:"runMachines:start",secrets:[o]});u.info(`Starting ${r} workers...`);let t=0;for(let f=1;f<=Number(r);f++){let m=`${n}/machines/${f}`;if(!await G.exists(m))throw u.error(`Machine ${f} doesn't exist at ${m}`),Error(`Machine ${f} not found. Please run 'hydra create' first or check your directory.`);try{await ei({index:f,labels:c,machineCwd:m,name:s,runnerGroup:a,token:o,url:i}),u.info(`Worker ${s}-${f} started successfully`),t++}catch(b){let y=b instanceof Error?b.message:String(b);u.error(`Failed to start worker ${s}-${f}:`,y)}}if(t===0)throw Error("No workers could be started");u.info(`${t} workers started. Press Ctrl+C to stop all machines`),process.on("SIGINT",async()=>{u.info("Gracefully shutting down workers..."),Xr(),process.exit(0)})}var Qr=O(()=>{nn();pn();Ci()});var Z={};to(Z,{help:()=>nr});function nr(n){if(n&&Oi[n]){console.info(Jo(Oi[n]));return}let r=[{description:"Initialize a new Hydra configuration file",name:"init"},{description:"Create and register new GitHub runner machines",name:"create"},{description:"Check runner health and diagnose issues",name:"health"},{description:"Remove GitHub runner machines",name:"remove"},{description:"Start existing GitHub runner machines",name:"run"},{description:"Check the status of GitHub runner machines",name:"status"},{description:"Generate runner configuration templates",name:"template"},{description:"Validate configuration file",name:"validate"},{description:"Watch and auto-restart runners on failure",name:"watch"},{description:"Migrate configuration to latest format",name:"migrate"},{description:"Show this help message",name:"help"}];console.info(Yo(`Hydra@${Un} - GitHub self-hosted runner manager`,"hydra <command> [options]",r,"Use hydra <command> --help for more information about a command."))}var Oi;var J=O(()=>{Q();sr();Oi={create:{description:"Create and register new GitHub runner machines",examples:[{command:"hydra create -t TOKEN -u https://github.com/org/repo",description:"Create a single runner"},{command:"hydra create -t TOKEN -u URL -m 3",description:"Create 3 runners"},{command:"hydra create -t TOKEN -u URL -l docker,gpu",description:"Create runner with labels"},{command:"hydra create -p production",description:"Create using production profile"}],name:"hydra create",notes:["Requires a GitHub personal access token with repo scope","Creates runners in ./gh-runners by default","Use --run to immediately start runners after creation"],options:[{description:"GitHub personal access token",flags:"-t, --token",type:"string"},{description:"Repository or organization URL",flags:"-u, --url",type:"string"},{description:"Runner name prefix",flags:"-n, --name",type:"string"},{description:"Number of machines to create",flags:"-m, --numberOfMachines",type:"number"},{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Runner labels (comma-separated)",flags:"-l, --labels",type:"string"},{description:"Runner group",flags:"-g, --runnerGroup",type:"string"},{description:"Operating system",flags:"-s, --os",type:"string"},{description:"Overwrite existing runners",flags:"-f, --overwrite",type:"boolean"},{description:"Start runners after creation",flags:"-r, --run",type:"boolean"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra create [options]"},health:{description:"Check runner health and diagnose issues",examples:[{command:"hydra health",description:"Check health of all runners"},{command:"hydra health --fix",description:"Auto-fix common issues"},{command:"hydra health -p production",description:"Check health using profile"}],name:"hydra health",notes:["Checks runner registration, connectivity, and configuration","Use --fix to automatically resolve common issues","Exit code 0 if healthy, 1 if issues found"],options:[{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Auto-fix common issues",flags:"--fix",type:"boolean"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra health [options]"},init:{description:"Initialize a new Hydra configuration file",examples:[{command:"hydra init",description:"Create hydra.json interactively"},{command:"hydra init --toml",description:"Create hydra.toml instead"}],name:"hydra init",options:[{description:"Use TOML format instead of JSON",flags:"--toml",type:"boolean"}],usage:"hydra init [options]"},migrate:{description:"Migrate configuration to latest format",examples:[{command:"hydra migrate",description:"Migrate configuration"},{command:"hydra migrate --dry-run",description:"Preview changes without applying"}],name:"hydra migrate",options:[{description:"Preview changes without applying",flags:"--dry-run",type:"boolean"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra migrate [options]"},remove:{description:"Remove GitHub runner machines",examples:[{command:"hydra remove -t TOKEN -u https://github.com/org/repo",description:"Remove all runners"},{command:"hydra remove -t TOKEN -u URL -m 2",description:"Remove 2 runners"},{command:"hydra remove -t TOKEN -u URL --force",description:"Force remove without confirmation"},{command:"hydra remove -p production",description:"Remove using production profile"}],name:"hydra remove",notes:["Requires a GitHub personal access token with repo scope","Removes runners from GitHub and deletes local files","Use --force to skip confirmation prompt"],options:[{description:"GitHub personal access token",flags:"-t, --token",type:"string"},{description:"Repository or organization URL",flags:"-u, --url",type:"string"},{description:"Number of machines to remove",flags:"-m, --numberOfMachines",type:"number"},{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Force removal without confirmation",flags:"-f, --force",type:"boolean"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra remove [options]"},run:{description:"Start existing GitHub runner machines",examples:[{command:"hydra run -t TOKEN -u https://github.com/org/repo",description:"Start all runners"},{command:"hydra run -t TOKEN -u URL -m 2",description:"Start 2 runners"},{command:"hydra run -p production",description:"Start using production profile"}],name:"hydra run",notes:["Requires a GitHub personal access token with repo scope","Runners must be created first using 'hydra create'","Runs in foreground, use Ctrl+C to stop"],options:[{description:"GitHub personal access token",flags:"-t, --token",type:"string"},{description:"Repository or organization URL",flags:"-u, --url",type:"string"},{description:"Runner name prefix",flags:"-n, --name",type:"string"},{description:"Number of machines to run",flags:"-m, --numberOfMachines",type:"number"},{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Runner labels (comma-separated)",flags:"-l, --labels",type:"string"},{description:"Runner group",flags:"-g, --runnerGroup",type:"string"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra run [options]"},status:{description:"Check the status of GitHub runner machines",examples:[{command:"hydra status",description:"Show status of all runners"},{command:"hydra status --json",description:"Output status as JSON"},{command:"hydra status -p production",description:"Check status using profile"}],name:"hydra status",notes:["Shows runner registration status and current state","Use --json for machine-readable output"],options:[{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Output as JSON",flags:"--json",type:"boolean"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra status [options]"},template:{description:"Generate runner configuration templates",examples:[{command:"hydra template",description:"Generate default template"},{command:"hydra template --type docker",description:"Generate Docker runner template"}],name:"hydra template",options:[{description:"Template type",flags:"--type",type:"string"},{description:"Output file path",flags:"-o, --output",type:"string"}],usage:"hydra template [options]"},validate:{description:"Validate configuration file",examples:[{command:"hydra validate",description:"Validate hydra.json"},{command:"hydra validate -c custom.toml",description:"Validate custom config file"}],name:"hydra validate",options:[{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra validate [options]"},watch:{description:"Watch and auto-restart runners on failure",examples:[{command:"hydra watch",description:"Watch all runners"},{command:"hydra watch -p production",description:"Watch using profile"}],name:"hydra watch",notes:["Monitors runners and restarts them if they fail","Runs in foreground, use Ctrl+C to stop"],options:[{description:"Runners directory",flags:"-d, --directory",type:"string"},{description:"Configuration profile",flags:"-p, --profile",type:"string"},{description:"Configuration file path",flags:"-c, --config",type:"string"}],usage:"hydra watch [options]"}}});var ki={};to(ki,{createMachines:()=>Fr});import{homedir as wc}from"os";import{join as bc}from"path";import{parseArgs as gc}from"util";var{$:Si}=globalThis.Bun;async function Fr(n){let r=U({prefix:"createMachines"}),o=n||await lc(),{overwrite:i,directory:s,numberOfMachines:c,os:a,run:u,name:t,labels:f,runnerGroup:m}=o,{token:b,url:y}=o;if(u){if(!y)throw Error("URL (-u) parameter is required when running machines");if(!b){let p=En(y),d=await V({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
64
|
-
${p}`});if(B(d)||!d)throw Error("Token is required to run machines");r.info("Opening GitHub runner settings..."),await Si`open ${p}`.quiet();let x=await P({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:($)=>{if(!$||$.trim().length===0)return"Token is required";return}});if(B(x))throw Error("Token is required to run machines");b=x.trim()}r=U({prefix:"createMachines",secrets:[b]})}if(r.info(`Creating ${c} machine directories in ${s}`),r.debug(`OS: ${a}, Name: ${t}, Labels: ${f||"none"}, Run: ${u}`),await G.exists(s))if(i)r.warn(`Directory ${s} exists, removing...`),await Si`rm -rf ${s}`;else throw Error(`Directory ${s} already exists. Use -f to overwrite.`);let e=await wi({directory:s,os:a});if(await Ri({directory:s,numberOfMachines:c,overwrite:i,runnerBase:e}),!u){r.info("Machine directories created. Use 'hydra run' to start them.");return}if(!y||!b){r.warn("Cannot start machines without URL and token"),r.info("Machine directories created. Use 'hydra run' with -u and -t to start them.");return}await vn({directory:s,labels:f,name:t,numberOfMachines:c,runnerGroup:m,token:b,url:y})}async function lc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:u}=await Promise.resolve().then(() => (J(),Z));u("create"),process.exit(0)}let{values:r}=gc({args:n,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},labels:{short:"l",type:"string"},name:{default:"runner",short:"n",type:"string"},numberOfMachines:{default:"1",short:"m",type:"string"},os:{default:"osx",short:"s",type:"string"},overwrite:{default:!1,short:"f",type:"boolean"},profile:{short:"p",type:"string"},run:{default:!1,short:"r",type:"boolean"},runnerGroup:{short:"g",type:"string"},template:{short:"T",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await W({configPath:r.config}),i=await T(o,r.profile),s;if(r.template)s=await hc(r.template);let c={directory:r.directory,labels:r.labels,name:r.name,numberOfMachines:r.numberOfMachines,os:r.os,overwrite:r.overwrite,run:r.run,runnerGroup:r.runnerGroup,token:r.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url},a=i||s?{directory:c.directory??i?.directory??s?.directory??`${process.cwd()}/gh-runners`,labels:c.labels??i?.labels??s?.labels,name:c.name??i?.name??s?.name??"runner",numberOfMachines:c.numberOfMachines??String(i?.numberOfMachines??s?.numberOfMachines)??"1",os:c.os??i?.os??s?.os??"osx",overwrite:c.overwrite??i?.overwrite??s?.overwrite??!1,run:c.run??i?.run??s?.run??!1,runnerGroup:c.runnerGroup??i?.runnerGroup??s?.runnerGroup,token:c.token||i?.token,url:c.url??i?.url??s?.url}:null;if(a)return a;return{directory:c.directory,labels:c.labels,name:c.name,numberOfMachines:c.numberOfMachines,os:c.os,overwrite:c.overwrite,run:c.run,runnerGroup:c.runnerGroup,token:c.token,url:c.url}}async function hc(n){let r=U({prefix:"loadTemplate"}),o="./hydra-templates.json",i=Bun.file("./hydra-templates.json");if(await i.exists())try{let a=await i.json();if(a&&typeof a==="object"&&"templates"in a&&a.templates&&typeof a.templates==="object"&&n in a.templates)return r.info(`Using local template: ${n}`),Zr(a.templates[n],a.templates)}catch(a){r.warn(`Failed to load local templates: ${a}`)}let s=bc(wc(),".hydra","templates.json"),c=Bun.file(s);if(await c.exists())try{let a=await c.json();if(a&&typeof a==="object"&&"templates"in a&&a.templates&&typeof a.templates==="object"&&n in a.templates)return r.info(`Using global template: ${n}`),Zr(a.templates[n],a.templates)}catch(a){r.warn(`Failed to load global templates: ${a}`)}r.warn(`Template '${n}' not found`);return}function Zr(n,r,o=new Set){if(n.name&&o.has(n.name))throw Error(`Circular template dependency detected: ${n.name}`);if(n.name)o.add(n.name);let i={};if(n.extends&&r[n.extends]){let f=r[n.extends];if(f)i=Zr(f,r,o)}let{name:s,description:c,extends:a,metadata:u,...t}=n;return{...i,...t}}var vr=O(()=>{I();fn();bi();$i();Qr();nn();pn()});sr();vr();I();Q();X();fn();import{existsSync as Gn}from"fs";import{readdir as _i}from"fs/promises";import{join as dn,resolve as xc}from"path";import{parseArgs as Rc}from"util";var{$:no}=globalThis.Bun;var $c=L({prefix:"hydra"}).child("health");async function Ec(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:s}=await Promise.resolve().then(() => (J(),Z));s("health"),process.exit(0)}let{values:r}=Rc({args:n,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},fix:{default:!1,short:"f",type:"boolean"},json:{default:!1,short:"j",type:"boolean"},profile:{short:"p",type:"string"},runner:{short:"r",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await W({configPath:r.config}),i=await T(o,r.profile);return{directory:r.directory||i?.directory||`${process.cwd()}/gh-runners`,fix:r.fix,json:r.json,runner:r.runner,token:r.token,url:r.url||i?.url}}async function Hi(){try{let n=await Ec(),r=xc(n.directory),o=dn(r,"machines");if(!Gn(o)){w.error(`No runners found in ${n.directory}`);return}let i=rn();i.start("Performing health checks...");let s=await _i(o),c=[];for(let a of s){if(n.runner&&a!==n.runner)continue;let u=dn(o,a),t=await ec(a,u,n);c.push(t)}if(i.stop("Health checks completed"),n.json){console.log(JSON.stringify(c,null,2));return}if(kc(c),n.fix)await _c(c,n)}catch(n){$c.error("Failed to perform health checks:",n),process.exit(1)}}async function ec(n,r,o){let i=[],s={configuration:!1,connectivity:!1,disk:{percentage:0,total:0,used:0},lastActivity:null,process:!1};try{let a=dn(r,".runner");if(Gn(a)){let u=await Bun.file(a).text(),t=await Cc(u.trim());if(s.process=t,!t)i.push("Runner process is not running")}else i.push("No PID file found")}catch{i.push("Could not check process status")}try{let a=await Oc(r);if(s.disk=a,a.percentage>90)i.push(`Low disk space: ${a.percentage.toFixed(1)}% used`)}catch{i.push("Could not check disk space")}try{let a=dn(r,"_diag");if(Gn(a)){let u=await _i(a),t=null;for(let f of u)if(f.endsWith(".log")){let m=await Bun.file(dn(a,f)).stat();if(!t||m.mtime>t)t=new Date(m.mtime)}if(s.lastActivity=t,t){let f=(Date.now()-t.getTime())/3600000;if(f>24)i.push(`No activity for ${Math.floor(f)} hours`)}}}catch{i.push("Could not check last activity")}try{let a=dn(r,".runner"),u=dn(r,".credentials");if(s.configuration=Gn(a)&&Gn(u),!s.configuration)i.push("Missing configuration files")}catch{i.push("Could not check configuration")}if(o.token&&o.url)try{let a=await Sc(o.url,o.token);if(s.connectivity=a,!a)i.push("Cannot connect to GitHub API")}catch{i.push("Failed to check GitHub connectivity")}let c="healthy";if(i.length===0)c="healthy";else if(i.some((a)=>a.includes("not running")||a.includes("Missing configuration")||a.includes("Cannot connect")))c="critical";else if(i.length>0)c="warning";return{checks:s,issues:i,runner:n,status:c}}async function Cc(n){try{return await no`kill -0 ${n}`.quiet(),!0}catch{return!1}}async function Oc(n){let o=(await no`df -k ${n} | tail -1`.text()).trim().split(/\s+/),i=Number.parseInt(o[1]||"0",10)*1024,s=Number.parseInt(o[2]||"0",10)*1024;return{percentage:Number.parseInt(o[4]?.replace("%","")||"0",10),total:i,used:s}}async function Sc(n,r){return Jn(async()=>{let o=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!o)return!1;let[,i,s]=o,c=s?`https://api.github.com/repos/${i}/${s}`:`https://api.github.com/orgs/${i}`;return(await fetch(c,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${r}`}})).ok},{maxAttempts:3})}function kc(n){console.log(),console.log(l.bold("\uD83C\uDFE5 Runner Health Status")),console.log("\u2500".repeat(80));let r={critical:"\u274C",healthy:"\u2705",unknown:"\u2753",warning:"\u26A0\uFE0F"},o={critical:l.error,healthy:l.success,unknown:l.dim,warning:l.warning};for(let s of n){let c=r[s.status],a=o[s.status];if(console.log(`${c} ${l.bold(`Runner ${s.runner}`)}: ${a(s.status.toUpperCase())}`),console.log(` Process: ${s.checks.process?"\u2705 Running":"\u274C Not running"}`),console.log(` Config: ${s.checks.configuration?"\u2705 Valid":"\u274C Missing"}`),s.checks.disk.total>0){let u=s.checks.disk.percentage>90?l.error:l.success;console.log(` Disk: ${u(`${s.checks.disk.percentage.toFixed(1)}% used`)}`)}if(s.checks.lastActivity){let t=(Date.now()-s.checks.lastActivity.getTime())/3600000>24?l.warning:l.success;console.log(` Last Activity: ${t(Hc(s.checks.lastActivity))}`)}if(s.checks.connectivity!==null)console.log(` GitHub API: ${s.checks.connectivity?"\u2705 Connected":"\u274C Disconnected"}`);if(s.issues.length>0){console.log(" Issues:");for(let u of s.issues)console.log(` - ${l.dim(u)}`)}console.log()}let i={critical:n.filter((s)=>s.status==="critical").length,healthy:n.filter((s)=>s.status==="healthy").length,total:n.length,warning:n.filter((s)=>s.status==="warning").length};console.log("\u2500".repeat(80)),console.log(`Summary: Total: ${i.total} | ${l.success(`Healthy: ${i.healthy}`)} | ${l.warning(`Warning: ${i.warning}`)} | ${l.error(`Critical: ${i.critical}`)}`)}async function _c(n,r){let o=n.filter((s)=>s.status==="critical");if(o.length===0){w.info("No critical issues found that require fixing");return}if(console.log(),!await V({initialValue:!1,message:`Found ${o.length} runners with critical issues. Attempt to fix?`}))return;for(let s of o){if(console.log(),w.info(`Attempting to fix runner ${s.runner}...`),!s.checks.process&&s.checks.configuration){w.info("Attempting to restart runner...");try{let c=dn(r.directory,"machines",s.runner);await no`cd ${c} && ./run.sh`.quiet(),w.success(`Runner ${s.runner} restarted successfully`)}catch(c){w.error(`Failed to restart runner ${s.runner}`)}}if(!s.checks.configuration)w.warning(`Runner ${s.runner} needs to be reconfigured. Run 'hydra create' to set up again.`)}}function Hc(n){let o=new Date().getTime()-n.getTime(),i=Math.floor(o/3600000);if(i<1)return`${Math.floor(o/60000)}m ago`;if(i<24)return`${i}h ago`;return`${Math.floor(i/24)}d ago`}J();I();Q();X();import{resolve as Gc}from"path";import{parseArgs as Nc}from"util";var{$:ro}=globalThis.Bun;var wn=L({prefix:"hydra"}).child("init");async function Gi(){let{toml:n}=await Uc(),r=n?"hydra.toml":"hydra.json",o=Gc(process.cwd(),r);if(await Bun.file(o).exists()){let b=await V({initialValue:!1,message:`Configuration file ${r} already exists. Overwrite?`});if(B(b)||!b)Gr("Configuration cancelled"),process.exit(0)}Nr(k.cyan("\uD83D\uDE80 Hydra Configuration Setup")),wn.info("This will create a configuration file with your runner settings."),wn.info("You can always edit the file later or create additional profiles.");let s=await qo({profileName:()=>P({message:"Profile name?",placeholder:"default"}),directory:()=>P({defaultValue:"./gh-runners",message:"Directory to store runners?",placeholder:"./gh-runners"}),name:()=>P({defaultValue:"runner",message:"Runner name prefix?",placeholder:"runner"}),labels:({results:b})=>{let y=b.name||"runner";return P({defaultValue:y,message:"Runner labels (comma-separated)?",placeholder:y})},numberOfMachines:()=>P({defaultValue:"1",message:"Number of runner machines?",placeholder:"1",validate:(b)=>{let y=Number.parseInt(b||"0",10);if(Number.isNaN(y)||y<1)return"Please enter a valid number greater than 0";return}}),url:()=>P({message:"GitHub repository or organization URL? (optional)",placeholder:"https://github.com/org/repo"})},{onCancel:()=>{Gr("Configuration cancelled"),process.exit(0)}}),{profileName:c,labels:a,numberOfMachines:u,...t}=s,f={defaultProfile:c,profiles:{[c]:{...t,labels:a,numberOfMachines:Number.parseInt(u,10),os:"osx",overwrite:!1,run:!1}}},m=JSON.stringify(f,null,2);if(await Bun.write(o,m),await xn(async()=>{await ro`chmod 600 ${o}`.quiet()},{logLevel:"warn",message:"Could not set secure file permissions"}),Pr(k.green(`\u2713 Configuration saved to ${r}`)),wn.info("Example usage:"),wn.info(` hydra create -p ${c} --token YOUR_TOKEN${s.url?"":" --url REPO_URL"}`),wn.info("You can add more profiles by editing the configuration file."),s.url)await Pc(s.url)}async function Pc(n){let r=/github\.com[:/]([^/]+)(?:\/([^/.]+))?/,o=n.match(r);if(!o)return;let[,i,s]=o,a=`https://github.com/${s?`${i}/${s}`:`organizations/${i}`}/settings/actions/runners`;wn.info(`Opening GitHub settings: ${a}`),await xn(async()=>{await ro`open ${a}`.quiet()},{fallback:async()=>{await xn(async()=>{await ro`xdg-open ${a}`.quiet()},{fallback:()=>{wn.info("Please open the URL manually to add a new runner token.")},logLevel:"info",message:"Alternative browser open method also failed"})},logLevel:"info",message:"Could not open browser automatically"})}async function Uc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:o}=await Promise.resolve().then(() => (J(),Z));o("init"),process.exit(0)}let{values:r}=Nc({args:n,options:{toml:{default:!1,short:"t",type:"boolean"}},strict:!0});return r}I();Q();import{parseArgs as Mc}from"util";var{$:Ni,Glob:Lc}=globalThis.Bun;async function jc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:o}=await Promise.resolve().then(() => (J(),Z));o("migrate"),process.exit(0)}let{values:r}=Mc({args:n,options:{all:{default:!1,short:"a",type:"boolean"},backup:{default:!0,short:"b",type:"boolean"},dryRun:{default:!1,short:"d",type:"boolean"},format:{short:"f",type:"string"},path:{short:"p",type:"string"}},strict:!0});return{all:r.all,backup:r.backup,dryRun:r.dryRun,format:r.format,path:r.path}}async function Pi(){let n=await jc();if(!n.path&&!n.all)n.path=await P({message:"Path to configuration file:",placeholder:"./hydra.json",validate:(i)=>{if(!i)return"Path is required";return}});let r=await qc(n);if(r.length===0){w.error("No configuration files found");return}w.info(`Found ${r.length} configuration file(s) to migrate`);let o=[];for(let i of r){let s=await Bc(i,n);o.push(s)}Dc(o,n)}async function qc(n){if(n.path){if(!await Bun.file(n.path).exists())throw Error(`Configuration file not found: ${n.path}`);return[n.path]}if(n.all){let r=new Lc("**/hydra.{json,toml}"),o=[];for await(let i of r.scan("."))if(!i.includes("node_modules")&&!i.includes(".git"))o.push(i);return o}return[]}async function Bc(n,r){let o=rn();o.start(`Migrating ${n}...`);try{let i=await Bun.file(n).text(),s=n.endsWith(".toml")?"toml":"json",c=r.format||s,a,u=[];if(s==="toml"){let f=`.temp-${Date.now()}.toml`;await Bun.write(f,i),a=(await import(f)).default,await Ni`rm ${f}`.quiet()}else a=JSON.parse(i);let t=await Vc(a,u);if(r.backup&&!r.dryRun){let f=`${n}.backup-${new Date().toISOString().replace(/:/g,"-")}`;await Bun.write(f,i),u.push(`Created backup at ${f}`)}if(!r.dryRun){let f=c!==s?n.replace(/\.(json|toml)$/,`.${c}`):n;if(c==="toml")await Ac(f,t);else await Bun.write(f,JSON.stringify(t,null,2));if(f!==n){if(await V({initialValue:!0,message:`Remove original file ${n}?`}))await Ni`rm ${n}`.quiet(),u.push(`Removed original file ${n}`)}u.push(`Migrated to ${f}`)}return o.stop(`Migrated ${n}`),{changes:u,path:n,success:!0}}catch(i){return o.stop(`Failed to migrate ${n}`),{error:i.message,path:n,success:!1}}}function rr(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}async function Vc(n,r){let o={profiles:{}};if(rr(n)&&"profiles"in n){let i=n.profiles;if(rr(i))for(let[s,c]of Object.entries(i))o.profiles[s]=await zc(c,r)}else if(rr(n)){let i={};if("directory"in n)i.directory=n.directory;if("name"in n)i.name=n.name;if("numberOfMachines"in n)i.numberOfMachines=n.numberOfMachines;if("os"in n)i.os=n.os;if("overwrite"in n)i.overwrite=n.overwrite;if("run"in n)i.run=n.run;if("token"in n)i.token=n.token;if("url"in n)i.url=n.url;if("labels"in n)i.labels=n.labels;if("runnerGroup"in n)i.runnerGroup=n.runnerGroup;o.profiles.default=i,r.push("Converted flat config to profile-based config")}if(!o.defaultProfile&&Object.keys(o.profiles).length===1)o.defaultProfile=Object.keys(o.profiles)[0],r.push("Set default profile to the only profile");return o}async function zc(n,r){if(!rr(n))return{directory:"./gh-runners",name:"runner",numberOfMachines:1,os:"osx",overwrite:!1,run:!1};let o={...n};if(!("directory"in o))o.directory="./gh-runners",r.push("Added default directory");if(!("name"in o))o.name="runner",r.push("Added default name");if(!("numberOfMachines"in o))o.numberOfMachines=1,r.push("Added default numberOfMachines");if(!("os"in o))o.os="osx",r.push("Added default os");if(!("overwrite"in o))o.overwrite=!1,r.push("Added default overwrite");if(!("run"in o))o.run=!1,r.push("Added default run");return o}async function Ac(n,r){let o="";if(r.defaultProfile)o+=`defaultProfile = "${r.defaultProfile}"
|
|
65
|
-
|
|
66
|
-
`;for(let[i,s]of Object.entries(r.profiles)){o+=`[profiles.${i}]
|
|
67
|
-
`;let c=Object.entries(s);for(let[a,u]of c){if(u===void 0||u===null)continue;if(typeof u==="string")o+=`${a} = "${u}"
|
|
68
|
-
`;else if(typeof u==="number")o+=`${a} = ${u}
|
|
69
|
-
`;else if(typeof u==="boolean")o+=`${a} = ${u}
|
|
70
|
-
`;else if(Array.isArray(u))o+=`${a} = [${u.map((t)=>`"${t}"`).join(", ")}]
|
|
71
|
-
`;else o+=`${a} = ${JSON.stringify(u)}
|
|
72
|
-
`}o+=`
|
|
73
|
-
`}await Bun.write(n,o.trim())}function Dc(n,r){if(w.info(""),r.dryRun)w.warn("DRY RUN MODE - No files were actually modified"),w.info("");let o=n.filter((s)=>s.success),i=n.filter((s)=>!s.success);if(o.length>0){w.success(`Successfully migrated ${o.length} file(s):`);for(let s of o)if(w.info(` ${l.value(s.path)}`),s.changes&&s.changes.length>0)for(let c of s.changes)w.info(` ${l.dim("\u2192")} ${c}`)}if(i.length>0){w.error(`Failed to migrate ${i.length} file(s):`);for(let s of i)w.error(` ${l.value(s.path)}: ${s.error}`)}w.info(""),w.info("Migration complete!")}I();fn();nn();pn();import{rm as oo}from"fs/promises";import{parseArgs as Ic}from"util";var{$:Ui}=globalThis.Bun;var F=U({prefix:"hydra:remove"});async function Mi(){let n=await Kc(),{directory:r,numberOfMachines:o,force:i}=n,{token:s,url:c}=n,a=`${r}/machines`;if(!await G.exists(a))throw Error(`Machines directory not found at ${a}. Nothing to remove.`);if(s)F=U({prefix:"hydra:remove",secrets:[s]});if(!s&&!i){if(!c)throw F.warn("No token or URL provided. Runners will not be unregistered from GitHub."),F.warn("Use --force to remove runners without unregistering them."),Error("Token (-t) and URL (-u) parameters are required or use --force");let u=En(c),t=await V({message:`No token provided. Would you like to open GitHub to get a runner token for unregistration?
|
|
74
|
-
${u}`});if(B(t)||!t)throw F.warn("Use --force to remove runners without unregistering them."),Error("Token is required to unregister runners (or use --force)");F.info("Opening GitHub runner settings..."),await Ui`open ${u}`.quiet();let f=await P({message:"Enter the runner removal token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(m)=>{if(!m||m.trim().length===0)return"Token is required";return}});if(B(f))throw F.warn("Use --force to remove runners without unregistering them."),Error("Token is required to unregister runners (or use --force)");s=f.trim()}if(s&&c)F.info("Unregistering runners from GitHub..."),await Wc({directory:r,numberOfMachines:o,token:s});else if(!i)throw F.warn("No token or URL provided. Runners will not be unregistered from GitHub."),F.warn("Use --force to remove runners without unregistering them."),Error("Token (-t) and URL (-u) parameters are required or use --force");await Tc({directory:r,numberOfMachines:o}),F.info("Runners successfully removed")}async function Kc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:c}=await Promise.resolve().then(() => (J(),Z));c("remove"),process.exit(0)}let{values:r}=Ic({args:n,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},force:{default:!1,short:"f",type:"boolean"},numberOfMachines:{default:"1",short:"m",type:"string"},profile:{short:"p",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await W({configPath:r.config}),i=await T(o,r.profile),s={directory:r.directory,force:r.force,numberOfMachines:r.numberOfMachines,token:r.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url};if(i)return{directory:s.directory??i.directory??`${process.cwd()}/gh-runners`,force:s.force,numberOfMachines:s.numberOfMachines??String(i.numberOfMachines)??"1",token:s.token||i?.token,url:s.url??i.url};return s}async function Wc({directory:n,numberOfMachines:r,token:o}){let i=U({prefix:"hydra:remove:unregister",secrets:[o]}),s=Number(r),c=(()=>{try{let y=Bun.spawnSync(["nproc"]);return Number.parseInt(y.stdout.toString().trim(),10)||4}catch{try{let y=Bun.spawnSync(["sysctl","-n","hw.ncpu"]);return Number.parseInt(y.stdout.toString().trim(),10)||4}catch{return 4}}})(),a=Math.min(Math.max(2,Math.floor(c/2)),s,8);i.info(`Unregistering ${s} runners with concurrency of ${a}`);let u=Array.from({length:s},(y,e)=>e+1).map((y)=>({execute:async()=>{let e=`${n}/machines/${y}`;if(!await G.exists(e))return i.debug(`Machine ${y} doesn't exist, skipping...`),{runnerIndex:y,status:"skipped"};try{return i.debug(`Unregistering machine ${y}...`),await Ui`${mi(e)}/config.sh remove`.quiet().env({...process.env,RUNNER_CFG_PAT:o}),i.info(`Successfully unregistered machine ${y} from GitHub`),{runnerIndex:y,status:"success"}}catch(p){return i.warn(`Unable to unregister machine ${y}: ${p}`),{error:p,runnerIndex:y,status:"failed"}}},runnerIndex:y})),t=[];for(let y=0;y<u.length;y+=a){let e=u.slice(y,y+a),p=await Promise.allSettled(e.map((d)=>d.execute()));t.push(...p)}let f=t.filter((y)=>y.status==="fulfilled"&&y.value?.status==="success").length,m=t.filter((y)=>y.status==="fulfilled"&&y.value?.status==="failed").length,b=t.filter((y)=>y.status==="fulfilled"&&y.value?.status==="skipped").length;i.info(`Unregistration complete: ${f} successful, ${m} failed, ${b} skipped`)}async function Tc({directory:n,numberOfMachines:r}){let o=U({prefix:"hydra:remove:removeDirectories",secrets:[]}),i=Number(r),s=Array.from({length:i},(t,f)=>f+1).map((t)=>({execute:async()=>{let f=`${n}/machines/${t}`;if(!await G.exists(f))return{runnerIndex:t,status:"skipped"};try{return await oo(f,{force:!0,recursive:!0}),o.debug(`Removed machine ${t} directory`),{runnerIndex:t,status:"success"}}catch(m){return o.error(`Error removing machine ${t} directory: ${m}`),{error:m,runnerIndex:t,status:"failed"}}},runnerIndex:t})),c=await Promise.allSettled(s.map((t)=>t.execute())),a=c.filter((t)=>t.status==="fulfilled"&&t.value?.status==="success").length,u=c.filter((t)=>t.status==="fulfilled"&&t.value?.status==="failed").length;if(o.info(`Directory removal complete: ${a} removed, ${u} failed`),u>0)throw Error(`Failed to remove ${u} runner directories`);try{let t=`${n}/machines`;if((await G.readdir(t)).length===0){if(await oo(t,{force:!0,recursive:!0}),(await G.readdir(n)).length===0)await oo(n,{force:!0,recursive:!0});F.info("Removed empty directories")}}catch(t){}}I();fn();Qr();nn();pn();import{parseArgs as Jc}from"util";var{$:Yc}=globalThis.Bun;var bn=U({prefix:"runMachines"});async function Li(n){let r=n||await Xc(),{directory:o,numberOfMachines:i,name:s,labels:c,runnerGroup:a}=r,{token:u,url:t}=r;if(!t)throw Error("URL (-u) parameter is required");if(!u){let b=En(t),y=await V({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
75
|
-
${b}`});if(B(y)||!y)throw Error("Token is required to run machines");bn.info("Opening GitHub runner settings..."),await Yc`open ${b}`.quiet();let e=await P({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(p)=>{if(!p||p.trim().length===0)return"Token is required";return}});if(B(e))throw Error("Token is required to run machines");u=e.trim()}bn=U({prefix:"runMachines",secrets:[u]}),bn.info(`Starting ${i} runners from ${o}`),bn.debug(`Name: ${s}, Labels: ${c||"none"}`);let f=`${o}/machines`,m=!1;if(!await G.exists(f))bn.warn(`Machines directory not found at ${f}`),m=!0;else for(let b=1;b<=Number(i);b++)if(!await G.exists(`${f}/${b}`)){bn.warn(`Machine directory ${b} is missing`),m=!0;break}if(m){bn.info("Creating machine directories before running...");let{createMachines:b}=await Promise.resolve().then(() => (vr(),ki));await b({directory:o,labels:c,name:s,numberOfMachines:i,os:"osx",overwrite:!1,run:!1,runnerGroup:a,token:void 0,url:void 0})}await vn({directory:o,labels:c,name:s,numberOfMachines:i,runnerGroup:a,token:u,url:t})}async function Xc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:c}=await Promise.resolve().then(() => (J(),Z));c("run"),process.exit(0)}let{values:r}=Jc({args:n,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},labels:{short:"l",type:"string"},name:{default:"runner",short:"n",type:"string"},numberOfMachines:{default:"1",short:"m",type:"string"},profile:{short:"p",type:"string"},runnerGroup:{short:"g",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await W({configPath:r.config}),i=await T(o,r.profile),s={directory:r.directory,labels:r.labels,name:r.name,numberOfMachines:r.numberOfMachines,runnerGroup:r.runnerGroup,token:r.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url};if(i)return{directory:s.directory??i.directory??`${process.cwd()}/gh-runners`,labels:s.labels??i.labels,name:s.name??i.name??"runner",numberOfMachines:s.numberOfMachines??String(i.numberOfMachines)??"1",runnerGroup:s.runnerGroup??i.runnerGroup,token:s.token||i?.token,url:s.url??i.url};return s}I();Q();X();fn();import{parseArgs as Qc}from"util";var{$:Zc}=globalThis.Bun;var en=L({prefix:"hydra"}).child("status");async function ji(){let n=await Fc(),{directory:r,token:o,url:i,json:s}=n;if(!o||!i)throw Error("Token (-t) and URL (-u) parameters are required");let c=rn();c.start("Fetching runner status...");try{let a=await vc(r),u=await na(i,o),t=ra(a,u);if(c.stop("Runner status fetched"),s)en.info(JSON.stringify(t,null,2));else oa(t)}catch(a){throw c.stop("Failed to fetch runner status"),a}}async function Fc(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:s}=await Promise.resolve().then(() => (J(),Z));s("status"),process.exit(0)}let{values:r}=Qc({args:n,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},json:{default:!1,short:"j",type:"boolean"},profile:{short:"p",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await W({configPath:r.config}),i=await T(o,r.profile);return{directory:r.directory||i?.directory||`${process.cwd()}/gh-runners`,json:r.json,token:r.token||i?.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url||i?.url}}async function vc(n){let r=`${n}/machines`;return await xn(async()=>{return(await Zc`ls ${r} 2>/dev/null || true`.quiet()).stdout.toString().trim().split(`
|
|
76
|
-
`).filter(Boolean)},{fallback:()=>{},logLevel:"debug",message:"No local runners found"})||[]}async function na(n,r){let o=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!o)throw Error("Invalid GitHub URL");let[,i,s]=o,c=s?`https://api.github.com/repos/${i}/${s}/actions/runners`:`https://api.github.com/orgs/${i}/actions/runners`;return Jn(async()=>{let a={Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${r}`},u=await fetch(c,{headers:a});if(!u.ok)throw Error(`GitHub API error: ${u.status} ${u.statusText}`);return await u.json()},{onRetry:(a,u)=>{w.warn(`Retrying GitHub API call (attempt ${a}): ${u.message}`)}})}function ra(n,r){let o=[],i=new Map(r.runners.map((s)=>[s.name,s]));for(let s of n){let c=`runner-${s}`,a=i.get(c);if(a)o.push({busy:a.busy,labels:a.labels.map((u)=>u.name),name:c,os:a.os,status:a.busy?"busy":a.status==="online"?"online":"offline"});else o.push({busy:!1,labels:[],name:c,os:"unknown",status:"offline"})}return o}function oa(n){if(n.length===0){w.info("No runners found");return}en.info("Runner Status:"),en.info("\u2500".repeat(80));let r={busy:l.busy,offline:l.offline,online:l.online};for(let i of n){let s=r[i.status],c=i.status.toUpperCase().padEnd(7);en.info(`${s("\u25CF")} ${s(c)} ${l.value(i.name.padEnd(20))} ${l.dim(`OS: ${i.os.padEnd(10)}`)} ${i.labels.length>0?l.dim(`Labels: ${i.labels.join(", ")}`):""}`)}en.info("\u2500".repeat(80));let o={busy:n.filter((i)=>i.status==="busy").length,offline:n.filter((i)=>i.status==="offline").length,online:n.filter((i)=>i.status==="online").length,total:n.length};en.info(`Summary: Total: ${o.total} | ${l.online(`Online: ${o.online}`)} | ${l.busy(`Busy: ${o.busy}`)} | ${l.offline(`Offline: ${o.offline}`)}`)}I();Q();import{homedir as qi}from"os";import{join as io}from"path";import{parseArgs as ia}from"util";var or={global:io(qi(),".hydra","templates.json"),local:"./hydra-templates.json"};async function sa(){let n=process.argv.slice(3);if(n.includes("--help")||n.includes("-h")){let{help:i}=await Promise.resolve().then(() => (J(),Z));i("template"),process.exit(0)}let{values:r}=ia({args:n,options:{action:{default:"list",short:"a",type:"string"},force:{default:!1,short:"f",type:"boolean"},from:{short:"F",type:"string"},global:{default:!1,short:"g",type:"boolean"},name:{short:"n",type:"string"}},strict:!0}),o=r.action;if(o&&!["list","create","use","delete","show"].includes(o))throw Error(`Unknown action: ${o}`);return{action:o,force:r.force,from:r.from,global:r.global,name:r.name}}async function Bi(){let n=await sa();if(!n.action)n.action=await tn({message:"What would you like to do?",options:[{label:"List templates",value:"list"},{label:"Create a new template",value:"create"},{label:"Use a template",value:"use"},{label:"Show template details",value:"show"},{label:"Delete a template",value:"delete"}]});switch(n.action){case"list":await ca();break;case"create":await aa(n);break;case"use":await ta(n);break;case"show":await ua(n);break;case"delete":await fa(n);break;default:w.error(`Unknown action: ${n.action}`),w.info("Available actions: list, create, use, show, delete")}}async function mn(n){let r=n?or.global:or.local,o=Bun.file(r);if(!await o.exists())return{templates:{},version:"1.0"};try{return await o.json()}catch{return{templates:{},version:"1.0"}}}async function Vi(n,r){let o=r?or.global:or.local;if(r){let i=io(qi(),".hydra");await Bun.write(io(i,".gitkeep"),"")}await Bun.write(o,JSON.stringify(n,null,2))}async function ca(){let n=await mn(!0),r=await mn(!1),o={...n.templates,...r.templates};if(Object.keys(o).length===0){w.info("No templates found"),w.info(""),w.info("Create a template with: hydra template create");return}w.info(l.value("Available Templates:")),w.info("");for(let[i,s]of Object.entries(o)){let a=i in n.templates?l.dim(" (global)"):"";if(w.info(` ${l.value(i)}${a}`),s.description)w.info(` ${l.dim(s.description)}`);if(s.extends)w.info(` ${l.dim(`Extends: ${s.extends}`)}`);let u=[];if(s.numberOfMachines)u.push(`machines: ${s.numberOfMachines}`);if(s.os)u.push(`os: ${s.os}`);if(s.labels)u.push(`labels: ${s.labels}`);if(u.length>0)w.info(` ${l.dim(u.join(", "))}`);w.info("")}}async function aa(n){let r=n.name||await P({message:"Template name:",placeholder:"my-template",validate:(m)=>{if(!m)return"Template name is required";if(!/^[a-zA-Z0-9-_]+$/.test(m))return"Template name can only contain letters, numbers, hyphens, and underscores";return}}),o=await mn(n.global??!1);if(!n.force&&r in o.templates){if(!await V({initialValue:!1,message:`Template '${r}' already exists. Overwrite?`})){w.info("Template creation cancelled");return}}let i=await P({message:"Description (optional):",placeholder:"Template for production runners"}),s={};if(n.from){let m=o.templates[n.from];if(m)s={...m},delete s.name,delete s.description,delete s.metadata,delete s.extends}let c=await P({initialValue:s.numberOfMachines?.toString()||"1",message:"Number of machines:",placeholder:s.numberOfMachines?.toString()||"1"}),a=await tn({initialValue:s.os||"osx",message:"Operating system:",options:[{label:"macOS",value:"osx"},{label:"Linux",value:"linux"},{label:"Windows",value:"windows"}]}),u=await P({initialValue:s.labels,message:"Labels (comma-separated, optional):",placeholder:s.labels||"self-hosted,x64"}),t=await P({initialValue:s.directory||"./gh-runners",message:"Runner directory:",placeholder:s.directory||"./gh-runners"}),f={description:i||void 0,directory:t,extends:n.from||void 0,labels:u||void 0,metadata:{author:process.env.USER||void 0,created:new Date().toISOString(),updated:new Date().toISOString()},name:r,numberOfMachines:Number.parseInt(c,10),os:a};o.templates[r]=f,await Vi(o,n.global??!1),w.success(`Template '${r}' created successfully`),w.info(""),w.info(`Use it with: hydra create --template ${r}`)}async function ta(n){let r=await mn(!0),o=await mn(!1),i={...r.templates,...o.templates};if(Object.keys(i).length===0){w.error("No templates found"),w.info("Create a template with: hydra template create");return}let s=n.name||await tn({message:"Select a template:",options:Object.entries(i).map(([t,f])=>({label:`${t}${f.description?` - ${f.description}`:""}`,value:t}))}),c=i[s];if(!c){w.error(`Template '${s}' not found`);return}let a=await so(c,i);if(w.info(""),w.info(l.value(`Using template: ${s}`)),w.info(""),w.info("This will create runners with the following configuration:"),w.info(` Number of machines: ${a.numberOfMachines||1}`),w.info(` OS: ${a.os||"osx"}`),w.info(` Directory: ${a.directory||"./gh-runners"}`),a.labels)w.info(` Labels: ${a.labels}`);w.info("");let u=await tn({message:"Where should this configuration be saved?",options:[{label:"Create hydra.json in current directory",value:"json"},{label:"Create hydra.toml in current directory",value:"toml"},{label:"Just show the command",value:"command"}]});if(u==="command"){let t=[];if(a.numberOfMachines)t.push(`-m ${a.numberOfMachines}`);if(a.os)t.push(`-s ${a.os}`);if(a.directory)t.push(`-d "${a.directory}"`);if(a.labels)t.push(`-l "${a.labels}"`);if(a.name)t.push(`-n "${a.name}"`);w.info("Run the following command:"),w.info(""),w.info(l.value(`hydra create ${t.join(" ")} -t <TOKEN> -u <URL>`)),w.info("")}else{let t={defaultProfile:"default",profiles:{default:a}},f=u==="json"?"hydra.json":"hydra.toml";if(u==="json")await Bun.write(f,JSON.stringify(t,null,2));else{let m=`defaultProfile = "default"
|
|
51
|
+
`)},info:(r,n)=>{w.message(r,{...n,symbol:m("blue",Zi)})},success:(r,n)=>{w.message(r,{...n,symbol:m("green",xi)})},step:(r,n)=>{w.message(r,{...n,symbol:m("green",Hr)})},warn:(r,n)=>{w.message(r,{...n,symbol:m("yellow",Qi)})},warning:(r,n)=>{w.warn(r,n)},error:(r,n)=>{w.message(r,{...n,symbol:m("red",Xi)})}};var qr=(r="",n)=>{let o=n?.output??process.stdout,i=n?.withGuide??q.withGuide?`${m("gray",zi)} `:"";o.write(`${i}${r}
|
|
52
|
+
`)},Gr=(r="",n)=>{let o=n?.output??process.stdout,i=n?.withGuide??q.withGuide?`${m("gray",P)}
|
|
53
|
+
${m("gray",er)} `:"";o.write(`${i}${r}
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
55
|
+
`)};var Oi=(r)=>r,Si=(r,n,o)=>{let i={hard:!0,trim:!1},e=O(r,n,i).split(`
|
|
56
|
+
`),t=e.reduce((c,f)=>Math.max(K(f),c),0),a=e.map(o).reduce((c,f)=>Math.max(K(f),c),0),s=n-(a-t);return O(r,s,i)},sr=(r="",n="",o)=>{let i=o?.output??x.stdout,e=o?.withGuide??q.withGuide,t=o?.format??Oi,a=["",...Si(r,dr(i)-6,t).split(`
|
|
57
|
+
`).map(t),""],s=K(n),c=Math.max(a.reduce((u,h)=>{let l=K(h);return l>u?l:u},0),s)+2,f=a.map((u)=>`${m("gray",P)} ${u}${" ".repeat(c-K(u))}${m("gray",P)}`).join(`
|
|
58
|
+
`),d=e?`${m("gray",P)}
|
|
59
|
+
`:"",g=e?Ai:Yi;i.write(`${d}${m("green",Hr)} ${m("reset",n)} ${m("gray",lo.repeat(Math.max(c-s-1,1))+Ji)}
|
|
60
|
+
${f}
|
|
61
|
+
${m("gray",g+lo.repeat(c+2)+Ki)}
|
|
62
|
+
`)};var Bi=(r)=>m("magenta",r),Y=({indicator:r="dots",onCancel:n,output:o=process.stdout,cancelMessage:i,errorMessage:e,frames:t=bn?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],delay:a=bn?80:120,signal:s,...c}={})=>{let f=qi(),d,g,u=!1,h=!1,l="",b,k=performance.now(),R=dr(o),C=c?.styleFrame??Bi,N=(U)=>{let Z=U>1?e??q.messages.error:i??q.messages.cancel;h=U===1,u&&(pr(Z,U),h&&typeof n=="function"&&n())},j=()=>N(2),F=()=>N(1),E=()=>{process.on("uncaughtExceptionMonitor",j),process.on("unhandledRejection",j),process.on("SIGINT",F),process.on("SIGTERM",F),process.on("exit",N),s&&s.addEventListener("abort",F)},M=()=>{process.removeListener("uncaughtExceptionMonitor",j),process.removeListener("unhandledRejection",j),process.removeListener("SIGINT",F),process.removeListener("SIGTERM",F),process.removeListener("exit",N),s&&s.removeEventListener("abort",F)},L=()=>{if(b===void 0)return;f&&o.write(`
|
|
63
|
+
`);let U=O(b,R,{hard:!0,trim:!1}).split(`
|
|
64
|
+
`);U.length>1&&o.write(hr.cursor.up(U.length-1)),o.write(hr.cursor.to(0)),o.write(hr.erase.down())},H=(U)=>U.replace(/\.+$/,""),V=(U)=>{let Z=(performance.now()-U)/1000,S=Math.floor(Z/60),B=Math.floor(Z%60);return S>0?`[${S}m ${B}s]`:`[${B}s]`},A=c.withGuide??q.withGuide,kr=(U="")=>{u=!0,d=to({output:o}),l=H(U),k=performance.now(),A&&o.write(`${m("gray",P)}
|
|
65
|
+
`);let Z=0,S=0;E(),g=setInterval(()=>{if(f&&l===b)return;L(),b=l;let B=C(t[Z]),yr;if(f)yr=`${B} ${l}...`;else if(r==="timer")yr=`${B} ${l} ${V(k)}`;else{let Bo=".".repeat(Math.floor(S)).slice(0,3);yr=`${B} ${l}${Bo}`}let So=O(yr,R,{hard:!0,trim:!1});o.write(So),Z=Z+1<t.length?Z+1:0,S=S<4?S+0.125:0},a)},pr=(U="",Z=0,S=!1)=>{if(!u)return;u=!1,clearInterval(g),L();let B=Z===0?m("green",Hr):Z===1?m("red",ho):m("red",bo);l=U??l,S||(r==="timer"?o.write(`${B} ${l} ${V(k)}
|
|
66
|
+
`):o.write(`${B} ${l}
|
|
67
|
+
`)),M(),d()};return{start:kr,stop:(U="")=>pr(U,0),message:(U="")=>{l=H(U??l)},cancel:(U="")=>pr(U,1),error:(U="")=>pr(U,2),clear:()=>pr("",0,!0),get isCancelled(){return h}}},yt={light:y("\u2500","-"),heavy:y("\u2501","="),block:y("\u2588","#")};var _i=[`${m("dim","\u2191/\u2193")} to navigate`,`${m("dim","Enter:")} confirm`],Mr=(r,n)=>r.includes(`
|
|
68
|
+
`)?r.split(`
|
|
69
|
+
`).map((o)=>n(o)).join(`
|
|
70
|
+
`):n(r),Co=(r)=>{let n=(i,e)=>{if(i===void 0)return"";let t=i.label??String(i.value);switch(e){case"disabled":return`${m("gray",Ur)} ${Mr(t,(a)=>m("gray",a))}${i.hint?` ${m("dim",`(${i.hint??"disabled"})`)}`:""}`;case"selected":return`${Mr(t,(a)=>m("dim",a))}`;case"active":return`${m("green",vn)} ${t}${i.hint?` ${m("dim",`(${i.hint})`)}`:""}`;case"cancelled":return`${Mr(t,(a)=>m(["strikethrough","dim"],a))}`;default:return`${m("dim",Ur)} ${Mr(t,(a)=>m("dim",a))}`}},o=r.showInstructions??!0;return new mo({options:r.options,signal:r.signal,input:r.input,output:r.output,initialValue:r.initialValue,render(){let i=r.withGuide??q.withGuide,e=`${Er(this.state)} `,t=`${vo(this.state)} `,a=ir(r.output,r.message,t,e),s=`${i?`${m("gray",P)}
|
|
71
|
+
`:""}${a}
|
|
72
|
+
`;switch(this.state){case"submit":{let c=i?`${m("gray",P)} `:"",f=ir(r.output,n(this.options[this.cursor],"selected"),c);return`${s}${f}`}case"cancel":{let c=i?`${m("gray",P)} `:"",f=ir(r.output,n(this.options[this.cursor],"cancelled"),c);return`${s}${f}${i?`
|
|
73
|
+
${m("gray",P)}`:""}`}default:{let c=i?`${m("cyan",P)} `:"",f=s.split(`
|
|
74
|
+
`).length,d=o?wo(_i,i):i?[m("cyan",er)]:[],g=d.join(`
|
|
75
|
+
`),u=d.length+1;return`${s}${c}${wn({output:r.output,cursor:this.cursor,options:this.options,maxItems:r.maxItems,columnPadding:c.length,rowPadding:f+u,style:(h,l)=>n(h,h.disabled?"disabled":l?"active":"inactive")}).join(`
|
|
76
|
+
${c}`)}
|
|
77
|
+
${g}
|
|
78
|
+
`}}}}).prompt()};var Lt=`${m("gray",P)} `;var Fo=(r)=>new hn({validate:r.validate,placeholder:r.placeholder,defaultValue:r.defaultValue,initialValue:r.initialValue,output:r.output,signal:r.signal,input:r.input,render(){let n=r?.withGuide??q.withGuide,o=`${`${n?`${m("gray",P)}
|
|
79
|
+
`:""}${Er(this.state)} `}${r.message}
|
|
80
|
+
`,i=r.placeholder&&r.placeholder.length>0?m("inverse",r.placeholder[0])+m("dim",r.placeholder.slice(1)):m(["inverse","hidden"],"_"),e=this.userInput?this.userInputWithCursor:i,t=this.value??"";switch(this.state){case"error":{let a=this.error?` ${m("yellow",this.error)}`:"",s=n?`${m("yellow",P)} `:"",c=n?m("yellow",er):"";return`${o.trim()}
|
|
81
|
+
${s}${e}
|
|
82
|
+
${c}${a}
|
|
83
|
+
`}case"submit":{let a=t?` ${m("dim",t)}`:"",s=n?m("gray",P):"";return`${o}${s}${a}`}case"cancel":{let a=t?` ${m(["strikethrough","dim"],t)}`:"",s=n?m("gray",P):"";return`${o}${s}${a}${t.trim()?`
|
|
84
|
+
${s}`:""}`}default:{let a=n?`${m("cyan",P)} `:"",s=n?m("cyan",er):"";return`${o}${a}${e}
|
|
85
|
+
${s}
|
|
86
|
+
`}}}}).prompt();var re=!process.env.NO_COLOR&&(process.env.FORCE_COLOR||(process.stdout?.isTTY??!1)),Lo=["black","blue","cyan","gray","green","magenta","red","white","yellow"],ne=["bold","dim","italic","underline","reset"],Io={bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",reset:"\x1B[0m",underline:"\x1B[4m"},oe={black:"\x1B[30m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",green:"\x1B[32m",magenta:"\x1B[35m",red:"\x1B[31m",white:"\x1B[37m",yellow:"\x1B[33m"},ie={black:"\x1B[40m",blue:"\x1B[44m",cyan:"\x1B[46m",gray:"\x1B[100m",green:"\x1B[42m",magenta:"\x1B[45m",red:"\x1B[41m",white:"\x1B[47m",yellow:"\x1B[43m"},ko={"\x1B[30m":"\x1B[90m","\x1B[31m":"\x1B[91m","\x1B[32m":"\x1B[92m","\x1B[33m":"\x1B[93m","\x1B[34m":"\x1B[94m","\x1B[35m":"\x1B[95m","\x1B[36m":"\x1B[96m","\x1B[37m":"\x1B[97m"};function zr(r){return(n)=>re?`${r}${n}${Io.reset}`:n}function ee(r){for(let n=0;n<r.length;n++){let o=r.charCodeAt(n);if(o<32&&o!==27)return!1}return!0}function yo({bright:r=!1,color:n}){let o=Bun.color(n,"ansi"),i=typeof o==="string"&&o.length>0&&ee(o)?o:oe[n];if(!i)return"";return r&&i in ko?ko[i]:i}var te=Lo.reduce((r,n)=>{let o=yo({color:n});if(o)r[n]=zr(o);let i=yo({bright:!0,color:n});if(i)r[`${n}Bright`]=zr(i);return r},{}),ae=ne.reduce((r,n)=>{return r[n]=zr(Io[n]),r},{}),se=Lo.reduce((r,n)=>{let o=ie[n];if(o){let i=`bg${n.charAt(0).toUpperCase()}${n.slice(1)}`;r[i]=zr(o)}return r},{}),p={...te,...ae,...se};function Wr(r){if(lr(r))throw new X;return r}function fe(r){return r.map((n)=>n.key?`${p.bold(n.key)} ${p.dim(n.text)}`:p.dim(n.text)).join(p.dim(" \xB7 "))}function Jr(r){w.info(fe(r))}var Ar={confirm:[{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],multiselect:[{key:"\u2191\u2193",text:"navigate"},{key:"Space",text:"toggle"},{key:"a",text:"all"},{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],select:[{key:"\u2191\u2193",text:"navigate"},{key:"Enter",text:"select"},{key:"Esc",text:"cancel"}],text:[{key:"Enter",text:"submit"},{key:"Esc",text:"cancel"}]};async function br(r){return Jr(Ar.confirm),Wr(await $o(r))}async function rr(r){return Jr(Ar.text),Wr(await Fo(r))}async function tr(r){return Jr(Ar.select),Wr(await Co({showInstructions:!1,...r}))}async function ar(r){return Jr(Ar.multiselect),Wr(await Po({showInstructions:!1,...r}))}var $={arg:p.magenta,cmd:p.cyan,default:p.blue,desc:p.white,flag:p.green,header:(r)=>p.bold(p.yellow(r)),hint:p.dim,name:(r)=>p.bold(p.cyan(r)),placeholder:p.magenta};class $n{metadata;commands;globalArgs;constructor(r,n,o){this.metadata=r;this.commands=n;this.globalArgs=o}version(){return`${$.name(this.metadata.name)} ${$.hint(this.metadata.version??"0.0.0")}`}global(){let r=[],{name:n,bin:o,version:i,description:e}=this.metadata;if(r.push(""),r.push(`${$.name(n)}${i?` ${$.hint(`v${i}`)}`:""}`),e)r.push($.desc(e));r.push(""),r.push($.header("Usage:")),r.push(` ${$.cmd(o)} ${$.placeholder("[command]")} ${$.hint("[options]")}`),r.push(""),r.push($.header("Commands:"));let t=Array.from(this.commands.values()).map((a)=>[` ${$.cmd(a.name)}`,$.desc(a.description)]);return r.push(...this.formatColumns(t)),r.push(""),r.push($.header("Options:")),r.push(...this.formatArgDefs(this.globalArgs)),r.push(""),r.push($.hint(`Run "${o} <command> --help" for command-specific options.`)),r.push(""),r.join(`
|
|
87
|
+
`)}command(r,n){let o=[],i=n??this.metadata.bin,e=`${$.cmd(i)} ${$.cmd(r.name)}`;o.push(""),o.push(`${$.name(r.name)} ${$.hint("-")} ${$.desc(r.description)}`),o.push(""),o.push($.header("Usage:"));let t=this.formatPositionalUsage(r.positionals);if(r.hasSubcommands())o.push(` ${e} ${$.placeholder("<subcommand>")} ${$.hint("[options]")}`);else{let c=[e];if(t)c.push(t);c.push($.hint("[options]")),o.push(` ${c.join(" ")}`)}if(r.prompts)o.push(` ${e} ${$.hint("- runs interactively")}`);if(o.push(""),r.hasSubcommands()){o.push($.header("Subcommands:"));let c=r.getSubcommands().map((f)=>[` ${$.cmd(f.name)}`,$.desc(f.description)]);o.push(...this.formatColumns(c)),o.push("")}if(Object.entries(r.positionals).length>0)o.push($.header("Arguments:")),o.push(...this.formatPositionalDefs(r.positionals)),o.push("");if(Object.entries(r.args).length>0)o.push($.header("Options:")),o.push(...this.formatArgDefs(r.args)),o.push("");return o.join(`
|
|
88
|
+
`)}formatPositionalUsage(r){return Object.entries(r).map(([n,o])=>{let i=o.variadic?`${n}...`:n;return o.required?$.arg(`<${i}>`):$.arg(`[${i}]`)}).join(" ")}formatPositionalDefs(r){let n=Object.entries(r).map(([o,i])=>{let e=i.variadic?`${o}...`:o,t=$.desc(i.description??""),a=i.required?"":$.hint(" (optional)");return[` ${$.arg(e)}`,`${t}${a}`]});return this.formatColumns(n)}formatArgDefs(r){let n=[];for(let[o,i]of Object.entries(r)){let t=`${i.alias?`${$.flag(`-${i.alias}`)}, `:" "}${$.flag(`--${o}`)}`,a=$.desc(i.description??""),s=i.default!==void 0?$.hint(` (default: ${$.default(this.formatDefault(i))})`):"";n.push([` ${t}`,`${a}${s}`])}return this.formatColumns(n)}formatDefault(r){if(r.type==="string")return`"${r.default}"`;return String(r.default)}formatColumns(r){if(r.length===0)return[];let n=Math.max(...r.map(([i])=>this.stripAnsi(i).length)),o=2;return r.map(([i,e])=>{let t=n-this.stripAnsi(i).length+o;return`${i}${" ".repeat(t)}${e}`})}stripAnsi(r){return r.replace(/\x1b\[[0-9;]*m/g,"")}}var nr=new Uint32Array(65536),me=(r,n)=>{let o=r.length,i=n.length,e=1<<o-1,t=-1,a=0,s=o,c=o;while(c--)nr[r.charCodeAt(c)]|=1<<c;for(c=0;c<i;c++){let f=nr[n.charCodeAt(c)],d=f|a;if(f|=(f&t)+t^t,a|=~(f|t),t&=f,a&e)s++;if(t&e)s--;a=a<<1|1,t=t<<1|~(d|a),a&=d}c=o;while(c--)nr[r.charCodeAt(c)]=0;return s},ue=(r,n)=>{let o=n.length,i=r.length,e=[],t=[],a=Math.ceil(o/32),s=Math.ceil(i/32);for(let l=0;l<a;l++)t[l]=-1,e[l]=0;let c=0;for(;c<s-1;c++){let l=0,b=-1,k=c*32,R=Math.min(32,i)+k;for(let C=k;C<R;C++)nr[r.charCodeAt(C)]|=1<<C;for(let C=0;C<o;C++){let N=nr[n.charCodeAt(C)],j=t[C/32|0]>>>C&1,F=e[C/32|0]>>>C&1,E=N|l,M=((N|F)&b)+b^b|N|F,L=l|~(M|b),H=b&M;if(L>>>31^j)t[C/32|0]^=1<<C;if(H>>>31^F)e[C/32|0]^=1<<C;L=L<<1|j,H=H<<1|F,b=H|~(E|L),l=L&E}for(let C=k;C<R;C++)nr[r.charCodeAt(C)]=0}let f=0,d=-1,g=c*32,u=Math.min(32,i-g)+g;for(let l=g;l<u;l++)nr[r.charCodeAt(l)]|=1<<l;let h=i;for(let l=0;l<o;l++){let b=nr[n.charCodeAt(l)],k=t[l/32|0]>>>l&1,R=e[l/32|0]>>>l&1,C=b|f,N=((b|R)&d)+d^d|b|R,j=f|~(N|d),F=d&N;if(h+=j>>>i-1&1,h-=F>>>i-1&1,j>>>31^k)t[l/32|0]^=1<<l;if(F>>>31^R)e[l/32|0]^=1<<l;j=j<<1|k,F=F<<1|R,d=F|~(C|j),f=j&C}for(let l=g;l<u;l++)nr[r.charCodeAt(l)]=0;return h},pe=(r,n)=>{if(r.length<n.length){let o=n;n=r,r=o}if(n.length===0)return r.length;if(r.length<=32)return me(r,n);return ue(r,n)},Do=(r,n)=>{let o=1/0,i=0;for(let e=0;e<n.length;e++){let t=pe(r,n[e]);if(t<o)o=t,i=e}return n[i]};function Kr(r,n,o,i){let e=Do(n,o);if(console.error(p.red(`Unknown ${r}: ${n}`)),e)console.error(p.yellow(`Did you mean "${e}"?`));console.error(`
|
|
89
|
+
Run "${i} --help" for usage.`),process.exit(1)}function vr(r,n){let o=(e)=>e&&typeof e==="object";if(!o(r)||!o(n))return n;let i={...r};for(let e of Object.keys(n)){let t=i[e],a=n[e];if(Array.isArray(t)&&Array.isArray(a))i[e]=[...a];else if(o(t)&&o(a))i[e]=vr(t,a);else i[e]=a}return i}function Pn(r){return r==null?[]:Array.isArray(r)?r:[r]}function le(r,n,o,i){var e,t=r[n],a=~i.string.indexOf(n)?o==null||o===!0?"":String(o):typeof o==="boolean"?o:~i.boolean.indexOf(n)?o==="false"?!1:o==="true"||(r._.push((e=+o,e*0===0)?e:o),!!o):(e=+o,e*0===0)?e:o;r[n]=t==null?a:Array.isArray(t)?t.concat(a):[t,a]}function Yr(r,n){r=r||[],n=n||{};var o,i,e,t,a,s={_:[]},c=0,f=0,d=0,g=r.length;let u=n.alias!==void 0,h=n.unknown!==void 0,l=n.default!==void 0;if(n.alias=n.alias||{},n.string=Pn(n.string),n.boolean=Pn(n.boolean),u)for(o in n.alias){i=n.alias[o]=Pn(n.alias[o]);for(c=0;c<i.length;c++)(n.alias[i[c]]=i.concat(o)).splice(c,1)}for(c=n.boolean.length;c-- >0;){i=n.alias[n.boolean[c]]||[];for(f=i.length;f-- >0;)n.boolean.push(i[f])}for(c=n.string.length;c-- >0;){i=n.alias[n.string[c]]||[];for(f=i.length;f-- >0;)n.string.push(i[f])}if(l){for(o in n.default)if(t=typeof n.default[o],i=n.alias[o]=n.alias[o]||[],n[t]!==void 0){n[t].push(o);for(c=0;c<i.length;c++)n[t].push(i[c])}}let b=h?Object.keys(n.alias):[];for(c=0;c<g;c++){if(e=r[c],e==="--"){s._=s._.concat(r.slice(++c));break}for(f=0;f<e.length;f++)if(e.charCodeAt(f)!==45)break;if(f===0)s._.push(e);else if(e.substring(f,f+3)==="no-"){if(t=e.substring(f+3),h&&!~b.indexOf(t))return n.unknown(e);s[t]=!1}else{for(d=f+1;d<e.length;d++)if(e.charCodeAt(d)===61)break;t=e.substring(f,d),a=e.substring(++d)||(c+1===g||(""+r[c+1]).charCodeAt(0)===45||r[++c]),i=f===2?[t]:t;for(d=0;d<i.length;d++){if(t=i[d],h&&!~b.indexOf(t))return n.unknown("-".repeat(f)+t);le(s,t,d+1<i.length||a,n)}}}if(l){for(o in n.default)if(s[o]===void 0)s[o]=n.default[o]}if(u)for(o in s){i=n.alias[o]||[];while(i.length>0)s[i.shift()]=s[o]}return s}function de(r){return r.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function Ro(r){let n={alias:{},boolean:[],default:{},string:[]};for(let[o,i]of Object.entries(r)){if(i.type==="boolean")n.boolean.push(o);else n.string.push(o);if(i.alias)n.alias[i.alias]=o;let e=de(o);if(e!==o)n.alias[e]=o;if(i.default!==void 0)n.default[o]=i.default}return n}function jo(r,n){let o={...r};for(let[i,e]of Object.entries(n)){if(e.type!=="number")continue;let t=r[i];if(t===void 0||typeof t==="boolean")continue;let a=Number(t);if(Number.isNaN(a))throw Error(`Invalid number for --${i}: "${t}"`);o[i]=a}return o}function Mo(r,n){let o=Ro(n),i=Yr(r,o),e=i._[0],t=e?r.indexOf(e):-1,{_:a,...s}=i,c=jo(s,n);return{command:e,flags:c,restArgs:t>=0?r.slice(t+1):[]}}function Cn(r,n={}){let o=Ro(n),i=Yr(r,o),{_:e,...t}=i;return{args:jo(t,n),rawPositionals:e}}function Fn(r,n){let o={},i=Object.entries(n);for(let[e,[t,a]]of i.entries())o[t]=a.variadic?r.slice(e):r[e];return o}function Uo(r,n){for(let[o,i]of Object.entries(n)){if(!i.required)continue;let e=r[o];if(Array.isArray(e)?e.length===0:!e)return`Missing required argument: <${o}${i.variadic?"...":""}>`}return null}var kn="__exit__";class cr{command;env;prefix;options;constructor(r,n,o,i={}){this.command=r;this.env=n;this.prefix=o;this.options=i}get commandPath(){return this.prefix?`${this.prefix} ${this.command.name}`:this.command.name}async route(r,n){if(n)await this.routeInteractive();else await this.routeDirect(r)}async routeDirect(r){let[n,...o]=r;if(n&&this.command.hasSubcommands()){let i=this.command.getSubcommand(n);if(i){await this.handleSubcommandRoute(i,o);return}if(!n.startsWith("-")){this.handleUnknownSubcommand(n);return}}await this.executeCommand(r)}handleUnknownSubcommand(r){let n=this.command.getSubcommands().map((o)=>o.name);Kr("subcommand",r,n,this.commandPath)}async handleSubcommandRoute(r,n){await new cr(r,this.env,this.commandPath).route(n,!1)}async executeCommand(r){if(this.isHelpRequest(r)){this.printHelp(this.command);return}if(this.command.hasSubcommands()&&!this.command.execute){this.printHelp(this.command);return}if(!this.command.execute)return;let{args:o,rawPositionals:i}=Cn(r,this.command.args),e=Fn(i,this.command.positionals),t=Uo(e,this.command.positionals);if(t)w.error(t),console.error(`
|
|
90
|
+
Run "${this.commandPath} --help" for usage.`),process.exit(1);let a=this.command.prompts&&i.length===0,s=this.buildContext(e,o,a);await this.command.execute(s)}async routeInteractive(){if(!this.command.hasSubcommands()){await this.executeInteractive();return}await this.runSubcommandMenu()}async executeInteractive(){let{args:r}=Cn([],this.command.args),n=Fn([],this.command.positionals),o=this.buildContext(n,r,!0);await this.command.execute?.(o)}async runSubcommandMenu(){while(!0){let r=await this.promptSubcommandSelectionOrBack();if(r===null)return;if(r===kn){this.options.onExit?.();return}let n=this.command.getSubcommand(r);if(n)await this.executeSubcommand(n)}}async promptSubcommandSelectionOrBack(){try{return await this.promptSubcommandSelection()}catch(r){if(r instanceof X){if(this.options.isRoot)this.options.onExit?.();return null}throw r}}async executeSubcommand(r){try{await new cr(r,this.env,this.commandPath).route([],!0)}catch(n){if(n instanceof X)return;if(n instanceof v){if(w.warn(p.yellow(n.message)),n.hint)w.info(p.dim(n.hint));return}throw n}}promptSubcommandSelection(){let{isRoot:r}=this.options,n=r?{hint:this.env.cli.exitHint,label:this.env.cli.exitLabel??"Exit",value:kn}:{hint:"Return to previous menu",label:"Back",value:kn};return tr({message:r?this.env.cli.promptMessage??"Select:":`${this.command.name}:`,options:[...this.command.getSubcommands().map((o)=>({hint:o.description,label:o.name,value:o.name})),n]})}buildContext(r,n,o){return{...this.env,args:n,interactive:o,positionals:r}}isHelpRequest(r){return r.includes("--help")||r.includes("-h")}printHelp(r){let n=r===this.command?this.prefix:this.commandPath;console.log(this.env.formatHelp(r,n))}}var ge={clearOnStart:!0,exitHint:"Close the CLI",exitLabel:"Exit",goodbyeMessage:"Goodbye!",name:"CLI",promptMessage:"What would you like to do?"};class yn{commands=new Map;metadata;configManager;help;bin;globalArgs={help:{alias:"h",description:"Show help",type:"boolean"},interactive:{alias:"i",description:"Enable interactive mode",type:"boolean"},version:{alias:"v",description:"Show version",type:"boolean"}};constructor(r,n){this.configManager=r,this.metadata={...ge,...n},this.bin=this.metadata.bin??this.metadata.name,this.init(),this.help=new $n({bin:this.bin,description:this.metadata.description,name:this.metadata.name,version:this.metadata.version},this.commands,this.globalArgs)}registerCommands(r){for(let n of r)n.init?.(),this.commands.set(n.name,n)}async run(r=process.argv.slice(2)){let{command:n,flags:o,restArgs:i}=Mo(r,this.globalArgs);if(o.version&&!n)return console.log(this.help.version());if(o.interactive&&!n)return this.runInteractive();if(!n)return console.log(this.help.global());if(n==="help")return this.printHelpFor(i[0]);await this.runDirect(n,i,!!o.help)}printHelpFor(r){if(!r)return console.log(this.help.global());let n=this.commands.get(r);if(!n)return this.handleUnknownCommand(r);console.log(this.help.command(n))}async runInteractive(){this.showIntro();let r=this.createVirtualRootCommand(),n={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)},o=new cr(r,n,this.bin,{isRoot:!0,onExit:()=>this.exit()});try{await o.route([],!0)}catch(i){this.handleError(i)}}createVirtualRootCommand(){return{description:this.metadata.description,getSubcommand:(r)=>this.commands.get(r),getSubcommands:()=>Array.from(this.commands.values()),hasSubcommands:()=>!0,name:this.metadata.name}}exit(){Gr(this.metadata.goodbyeMessage),process.exit(0)}async runDirect(r,n,o){let i=this.commands.get(r);if(!i)return this.handleUnknownCommand(r);let e=n.length>0&&!n[0]?.startsWith("-");if(o&&!e)return console.log(this.help.command(i));try{let t={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)};await new cr(i,t,this.bin).route(n,!1)}catch(t){this.handleError(t)}}showIntro(){if(this.metadata.clearOnStart)console.clear();let r=this.metadata.version?` v${this.metadata.version}`:"";qr(`${p.bgCyan(p.black(` ${this.metadata.name}${r} `))}`)}handleUnknownCommand(r){let n=Array.from(this.commands.keys());Kr("command",r,n,this.bin)}handleError(r){if(this.metadata.onError?.(r))return;if(r instanceof X)process.exit(0);if(r instanceof v){if(w.warn(p.yellow(r.message)),r.hint)w.info(p.dim(r.hint));process.exit(0)}if(r instanceof Error)w.error(p.red(r.message)),process.exit(1);console.error(p.red("Error:"),r),process.exit(1)}}class wr{args={};positionals={};prompts=!1;subcommands=new Map;registerSubcommands(r){for(let n of r)n.init?.(),this.subcommands.set(n.name,n)}hasSubcommands(){return this.subcommands.size>0}getSubcommand(r){return this.subcommands.get(r)}getSubcommands(){return Array.from(this.subcommands.values())}}function fr(r){return r}function G(r){return r}import mr from"fs";import Ho from"path";class Ln{config;configPath;defaultConfig;constructor(r,n){this.configPath=Ho.resolve(r),this.defaultConfig=n,this.config=this.loadConfig()}get(r){return this.config[r]}set(r,n){this.config[r]=n,this.save()}delete(r){delete this.config[r],this.save()}exists(){return mr.existsSync(this.configPath)}getAll(){return vr({},this.config)}save(r){if(r)this.config={...r};this.ensureDirectoryExists();try{mr.writeFileSync(this.configPath,JSON.stringify(this.config,null,2))}catch(n){console.error(`Failed to save config to ${this.configPath}:`,n)}}ensureDirectoryExists(){let r=Ho.dirname(this.configPath);if(!mr.existsSync(r))try{mr.mkdirSync(r,{recursive:!0})}catch(n){console.error(`Failed to create config directory at ${r}:`,n)}}loadConfig(){if(!mr.existsSync(this.configPath))return{...this.defaultConfig};try{let r=mr.readFileSync(this.configPath,"utf-8"),n=JSON.parse(r);return vr({...this.defaultConfig},n)}catch{return console.warn(`Config file corrupted at ${this.configPath}. Using defaults.`),{...this.defaultConfig}}}}var Eo="0.6.0";import{join as De}from"path";class I extends wr{}import{existsSync as Fr}from"fs";import{cp as Ce,link as Fe,mkdir as Un,readdir as Ko,readFile as Hn,readlink as ke,rm as En,symlink as ye,unlink as Yo,writeFile as Le}from"fs/promises";import{join as D,resolve as xr}from"path";var Zr="hydra";var No=".hydra/config.json",$r=".hydra/shared",Pr=".hydra/runners",Cr="default",qo={profiles:{}};import{existsSync as be}from"fs";import{readdir as ve,stat as we}from"fs/promises";import{join as $e}from"path";var In="_diag",Go={runner:/^Runner_.+\.log$/,worker:/^Worker_.+\.log$/},zo=1024,Wo=["B","KB","MB","GB"],Pe=1;function Jo(r){if(Go.worker.test(r))return"worker";if(Go.runner.test(r))return"runner";return null}function Ao(r){return[...r].sort((n,o)=>o.mtime.getTime()-n.mtime.getTime())}async function Dn(r){if(!be(r))return[];let n=await ve(r,{withFileTypes:!0}),o=[];for(let i of n){if(!i.isFile())continue;let e=Jo(i.name);if(!e)continue;let t=$e(r,i.name),a=await we(t);o.push({mtime:a.mtime,name:i.name,path:t,size:a.size,type:e})}return Ao(o)}function Rn(r,n){let o=r.find((e)=>e.type===n);if(o)return{fallback:!1,file:o};let i=r[0];return i?{fallback:!0,file:i}:null}function jn(r,n){if(n<=0)return"";let o=r.endsWith(`
|
|
91
|
+
`)?r.slice(0,-1):r;if(o==="")return"";return o.split(`
|
|
92
|
+
`).slice(-n).join(`
|
|
93
|
+
`)}function Mn(r){let n=r,o=0;while(n>=zo&&o<Wo.length-1)n/=zo,o++;return`${o===0?String(n):n.toFixed(Pe)} ${Wo[o]??"B"}`}var Zo="actions/runner",Ie={linux:"linux-x64",osx:"osx-arm64",windows:"win-x64"},xo=["bin"],Qo=["externals"];class Qr{profile;sharedPath=null;constructor(r){this.profile=r}async download(){let r=Ie[this.profile.os],n=await this.getLatestVersion(),o=D($r,"github",n);if(Fr(o))return this.sharedPath=o,{path:o,version:n};await Un(o,{recursive:!0});let i=`actions-runner-${r}-${n}.tar.gz`,e=D(o,i),t=`https://github.com/${Zo}/releases/download/v${n}/${i}`;return await Bun.$`curl -sL -o ${e} ${t}`,await Bun.$`tar xzf ${e} -C ${o}`,await Yo(e),this.sharedPath=o,{path:o,version:n}}async create(r){let n=await this.ensureDownloaded(),o=[];for(let i of r){let e=D(this.profile.directory,i);await this.setupRunnerDir(n,e),await this.registerRunner(e,i),o.push({directory:e,id:i,name:i,status:"registered"})}return o}async remove(r){for(let n of r){let o=D(this.profile.directory,n);if(!Fr(D(o,".runner")))continue;let i=await this.fetchRemovalToken(o);await Bun.$`bash ./config.sh remove --token ${i}`.cwd(o).quiet().nothrow()}}async start(r){for(let n of r){let o=D(this.profile.directory,n),i=await this.readPidFile(o);if(i&&this.isProcessRunning(i))continue;let e=Bun.spawn(["bash","./run.sh"],{cwd:xr(o),stderr:"pipe",stdout:"pipe"});e.unref(),await this.writePidFile(o,e.pid)}}async stop(r){for(let n of r){let o=D(this.profile.directory,n);if(!await this.readPidFile(o))continue;let e=xr(o);await Bun.$`pkill -f ${e}`.quiet().nothrow(),await this.removePidFile(o)}}async list(){let r=this.profile.directory;if(!Fr(r))return[];let n=await Ko(r,{withFileTypes:!0}),o=[];for(let i of n){if(!i.isDirectory())continue;let e=D(r,i.name);o.push(await this.getRunnerStatus(e,i.name))}return o}async currentVersion(r){let n=D(this.profile.directory,r);return this.detectVersion(n)}async logFiles(r){return Dn(D(this.profile.directory,r,In))}async update(r){let n=await this.ensureDownloaded();for(let o of r){let i=D(this.profile.directory,o);await this.removeRunnerBinaries(i),await this.setupRunnerDir(n,i)}}async getRunnerStatus(r,n){let o=await this.readRunnerName(r),i=await this.readPidFile(r),e=i!==null&&this.isProcessRunning(i),t="unknown";if(e)t="running";else if(Fr(D(r,".runner")))t="registered";return{directory:r,id:n,name:o,pid:e?i:void 0,status:t}}async ensureDownloaded(){if(this.sharedPath)return this.sharedPath;let{path:r}=await this.download();return r}async setupRunnerDir(r,n){await Un(n,{recursive:!0});for(let o of xo)await this.hardLinkDir(D(r,o),D(n,o));for(let o of Qo){let i=xr(r,o),e=D(n,o);if(!Fr(e))await ye(i,e)}for(let o of["*.sh","*.sh.template"]){let i=await Array.fromAsync(new Bun.Glob(o).scan(r));for(let e of i)await Ce(D(r,e),D(n,e))}}async registerRunner(r,n){let o=await this.fetchRegistrationToken(),i=["--url",this.profile.url,"--token",o,"--name",n,"--unattended"];if(this.profile.labels)i.push("--labels",this.profile.labels);if(this.profile.runnerGroup)i.push("--runnergroup",this.profile.runnerGroup);await Bun.$`bash ./config.sh ${i}`.cwd(r).quiet()}async fetchRegistrationToken(){let{owner:r,repo:n}=this.parseUrl(this.profile.url),i=(await Bun.$`gh api repos/${r}/${n}/actions/runners/registration-token --method POST --jq .token`.quiet()).stdout.toString().trim();if(!i)throw Error(`Failed to fetch registration token for ${r}/${n}`);return i}async fetchRemovalToken(r){let n=await Hn(D(r,".runner"),"utf-8"),i=JSON.parse(this.stripBom(n)).gitHubUrl;if(!i)throw Error("Cannot determine GitHub URL from runner config");let{owner:e,repo:t}=this.parseUrl(i);return(await Bun.$`gh api repos/${e}/${t}/actions/runners/remove-token --method POST --jq .token`.quiet()).stdout.toString().trim()}async getLatestVersion(){return(await Bun.$`gh api repos/${Zo}/releases/latest --jq .tag_name`.quiet()).stdout.toString().trim().replace(/^v/,"")}parseUrl(r){let n=r.match(/github\.com\/([^/]+)\/([^/.]+)/);if(!n?.[1]||!n[2])throw Error(`Invalid GitHub URL: ${r}`);return{owner:n[1],repo:n[2]}}pidFilePath(r){return xr(r,".pid")}async writePidFile(r,n){await Le(this.pidFilePath(r),String(n))}async readPidFile(r){try{let n=await Hn(this.pidFilePath(r),"utf-8");return Number.parseInt(n.trim(),10)}catch{return null}}async removePidFile(r){try{await Yo(this.pidFilePath(r))}catch{}}async readRunnerName(r){try{let n=await Hn(D(r,".runner"),"utf-8");return JSON.parse(this.stripBom(n)).agentName??"unknown"}catch{return"unknown"}}async hardLinkDir(r,n){await Un(n,{recursive:!0});let o=await Ko(r,{withFileTypes:!0});for(let i of o){let e=D(r,i.name),t=D(n,i.name);if(i.isDirectory())await this.hardLinkDir(e,t);else await Fe(e,t)}}async detectVersion(r){try{return(await ke(D(r,"externals"))).match(/github\/([^/]+)/)?.[1]??null}catch{return null}}async removeRunnerBinaries(r){for(let n of xo)await En(D(r,n),{force:!0,recursive:!0});for(let n of Qo)await En(D(r,n),{force:!0});for(let n of["*.sh","*.sh.template"]){let o=await Array.fromAsync(new Bun.Glob(n).scan(r));for(let i of o)await En(D(r,i),{force:!0})}}stripBom(r){return r.replace(/^\uFEFF/,"")}isProcessRunning(r){try{return process.kill(r,0),!0}catch{return!1}}}function z(r){switch(r.provider){case"github":return new Qr(r);default:throw Error(`Runner provider "${r.provider}" is not yet implemented`)}}function ur(r,n){if(r.length===0)return n;for(let o of r)if(!n.includes(o))throw new v(`Runner "${o}" not found`);return r}function J(r,n){let o=r.get("profiles");if(Object.keys(o).length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=n??r.get("defaultProfile")??Cr,e=o[i];if(!e)throw new v(`Profile "${i}" not found`);return{name:i,profile:e}}async function Q(r){let n=r.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");if(o.length===1)return o[0];return tr({message:"Select profile",options:o.map((i)=>({label:i,value:i,hint:n[i]?.url}))})}var Re=G({profile:{description:"Profile name"},count:{description:"Number of runners to create (overrides profile)"}});class Xr extends I{name="create";description="Create and register runners";positionals=Re;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),i=r.interactive?await this.promptCount(o.numberOfMachines):r.positionals.count?Number.parseInt(r.positionals.count,10):o.numberOfMachines;if(!i||i<1)throw new v("Runner count must be at least 1");let e=z(o),t=Y();t.start("Downloading runner binary...");let{version:a}=await e.download();t.stop(`Runner v${a} ready`);let s=r.config.get("runners")??[],c=s.filter((l)=>l.profile===n),f=i-c.length;if(f<=0){w.warn(`Already have ${c.length} runner(s) for profile "${n}". Nothing to create.`);return}let d=new Set(s.map((l)=>l.id)),g=1;for(let l=0;l<f;){let b=`${o.name}-${g++}`;if(d.has(b))continue;l++,t.start(`Registering ${b}...`),await e.create([b]),t.stop(`${p.green("+")} ${b}`),s.push({createdAt:new Date().toISOString(),directory:De(o.directory,b),id:b,name:b,profile:n,provider:o.provider,url:o.url})}r.config.set("runners",s);let h=n===r.config.get("defaultProfile")?"":` ${n}`;w.info(`${p.green("Created")} ${f} runner(s) for "${n}". Run ${p.green(`hydra start${h}`)} to start them.`)}async promptCount(r){let n=await rr({initialValue:String(r),message:"Number of runners to create",validate:(o)=>{let i=Number.parseInt(o??"",10);if(Number.isNaN(i)||i<1)return"Must be a positive number";return}});return Number.parseInt(n,10)}}import{existsSync as Xo}from"fs";import{mkdir as Vo}from"fs/promises";var je=G({url:{description:"GitHub repository or organization URL"}}),Me=fr({force:{alias:"f",default:!1,description:"Overwrite existing config",type:"boolean"},labels:{alias:"l",description:"Comma-separated runner labels",type:"string"},name:{alias:"n",description:"Base name for runners",type:"string"},profile:{alias:"p",description:"Profile name",type:"string"},runners:{alias:"c",description:"Number of runners to create",type:"number"}});class Vr extends I{name="init";description="Initialize Hydra runner manager";positionals=je;args=Me;prompts=!0;async execute(r){let n=r.interactive?await this.promptProfileName(r):r.args.profile??Cr,o=!r.config.exists();if(!o&&r.config.get("profiles")[n]&&!r.args.force){if(!r.interactive)throw new v(`Profile "${n}" already exists. Use --force to overwrite.`);if(!await br({initialValue:!1,message:`Profile "${n}" already exists. Overwrite?`}))return}await this.ensureDirectories();let e=r.interactive?await this.runInitForm():this.buildProfileFromArgs(r),t=o?{}:{...r.config.get("profiles")};if(t[n]=e,r.config.set("profiles",t),!r.config.get("defaultProfile"))r.config.set("defaultProfile",n);sr([`${p.dim("Profile:")} ${n}`,`${p.dim("URL:")} ${e.url}`,`${p.dim("Runners:")} ${e.numberOfMachines}`,`${p.dim("Name:")} ${e.name}`,e.labels?`${p.dim("Labels:")} ${e.labels}`:"","",`Run ${p.green(`${Zr} create${n!==r.config.get("defaultProfile")?` ${n}`:""}`)} to provision runners.`].filter(Boolean).join(`
|
|
94
|
+
`),p.green(o?"Hydra initialized":`Profile "${n}" added`))}async promptProfileName(r){return rr({initialValue:r.args.profile??Cr,message:"Profile name"})}async ensureDirectories(){if(!Xo($r))await Vo($r,{recursive:!0});if(!Xo(Pr))await Vo(Pr,{recursive:!0})}async runInitForm(){let r=await Nr({url:()=>rr({message:"GitHub repository or organization URL",placeholder:"https://github.com/owner/repo",validate:(n)=>{if(!n)return"URL is required";try{new URL(n)}catch{return"Must be a valid URL"}return}}),name:()=>rr({initialValue:"runner",message:"Base name for runners",placeholder:"runner"}),runners:()=>rr({initialValue:"1",message:"Number of runners",placeholder:"1",validate:(n)=>{if(!n)return"Must be a positive number";let o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1)return"Must be a positive number";return}}),labels:()=>rr({message:"Additional labels (comma-separated, optional)",placeholder:"self-hosted,macOS,ARM64"})},{onCancel:()=>{throw new X}});return{directory:Pr,labels:r.labels||void 0,name:r.name,numberOfMachines:Number.parseInt(r.runners,10)||1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:r.url}}buildProfileFromArgs(r){if(!r.positionals.url)throw new v("URL is required","Usage: hydra init <url>");return this.validateUrl(r.positionals.url),this.validateRunnerCount(r.args.runners),{directory:Pr,labels:r.args.labels,name:r.args.name??"runner",numberOfMachines:r.args.runners??1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:r.positionals.url}}validateUrl(r){try{new URL(r)}catch{throw new v(`Invalid URL: ${r}`)}}validateRunnerCount(r){if(r!==void 0&&r<1)throw new v("Runner count must be at least 1")}detectOs(){let r=process.platform;if(r==="darwin")return"osx";if(r==="win32")return"windows";return"linux"}}import{existsSync as Ue}from"fs";import{readFile as He}from"fs/promises";var Ee=100,Ne={runner:"runner daemon log",worker:"job log"},qe=fr({lines:{alias:"n",default:Ee,description:"Number of lines to tail",type:"number"},list:{alias:"l",default:!1,description:"List available log files instead of printing content",type:"boolean"},open:{alias:"o",default:!1,description:"Open the log file in $EDITOR instead of printing",type:"boolean"},runner:{alias:"r",default:!1,description:"Show the runner daemon log instead of the latest job log",type:"boolean"}}),Ge=G({id:{description:"Runner ID"}});class Or extends I{name="logs";description="Inspect logs of the latest jobs";args=qe;positionals=Ge;async execute(r){let n=r.config.get("runners")??[];if(n.length===0)throw new v("No runners found","Run hydra create to provision runners");let o=await this.resolveEntry(r,n),i=r.config.get("profiles")[o.profile];if(!i)throw new v(`Profile "${o.profile}" not found for runner "${o.id}"`,"Run hydra init to set it up");if(!Ue(o.directory))throw new v(`Runner directory not found: ${o.directory}`,"Run hydra create to provision this runner");let t=await z(i).logFiles(o.id);if(t.length===0)this.noLogs(o.id);if(r.args.list){this.printList(o,t);return}let a=this.selectFile(r,o,t);if(r.args.open){await this.openFile(a);return}await this.printTail(o,a,r.args.lines)}async resolveEntry(r,n){let o=r.positionals.id;if(o){let e=n.find((t)=>t.id===o);if(!e)throw new v(`Runner "${o}" not found`,`Known runners: ${n.map((t)=>t.id).join(", ")}`);return e}if(r.interactive)return tr({message:"Select runner",options:n.map((e)=>({hint:e.profile,label:e.name,value:e}))});let i=n[0];if(n.length===1&&i)return i;throw new v("Multiple runners found",`Pass a runner id: hydra logs <id> (${n.map((e)=>e.id).join(", ")})`)}selectFile(r,n,o){if(r.args.runner){let e=o.find((t)=>t.type==="runner");if(!e)throw new v(`No runner daemon logs found for "${n.id}"`,"Start the runner first: hydra start");return e}let i=Rn(o,"worker");if(!i)this.noLogs(n.id);if(i.fallback)w.warn(p.yellow("No job (Worker) logs yet; showing the runner daemon log instead"));return i.file}noLogs(r){throw new v(`No logs found for runner "${r}"`,"Logs appear once the runner has started; run hydra start")}printList(r,n){let o=[`${p.bold(r.name)} ${p.dim(r.directory)}`];for(let i of n){let e=i.type==="worker"?p.green("worker"):p.blue("runner");o.push(` ${e} ${i.name} ${p.dim(`${i.mtime.toISOString()} \xB7 ${Mn(i.size)}`)}`)}w.info(o.join(`
|
|
95
|
+
`))}async printTail(r,n,o){let i=await He(n.path,"utf-8"),e=[`${p.bold(r.name)} ${p.dim(Ne[n.type])}`,p.dim(n.path),p.dim(`Last modified: ${n.mtime.toISOString()}`)];w.info(e.join(`
|
|
96
|
+
`)),console.log(jn(i,o))}async openFile(r){let n=(process.env.EDITOR??"").split(" ").filter(Boolean),o=n[0];if(o){await Bun.spawn([o,...n.slice(1),r.path],{stderr:"inherit",stdin:"inherit",stdout:"inherit"}).exited;return}if(process.platform==="darwin"){await Bun.$`open ${r.path}`.quiet();return}throw new v("No editor configured","Set $EDITOR to open log files")}}var ze=G({name:{description:"Profile name to set as default"}});class Nn extends I{name="default";description="Set the default profile";positionals=ze;async execute(r){let n=r.interactive?await Q(r.config):r.positionals.name;if(!n)throw new v("Profile name is required","Usage: hydra profile default <name>");let{name:o}=J(r.config,n);if(r.config.get("defaultProfile")===o){w.info(`"${o}" is already the default profile.`);return}r.config.set("defaultProfile",o),w.info(`${p.green("Default profile set to")} "${o}".`)}}class qn extends I{name="list";description="List all profiles";async execute(r){let n=r.config.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=r.config.get("runners")??[],e=r.config.get("defaultProfile");for(let t of o){let a=n[t],c=await z(a).list(),f=i.filter((b)=>b.profile===t),d=new Set(c.filter((b)=>b.status==="running").map((b)=>b.id)),g=f.filter((b)=>d.has(b.id)).length,u=t===e,h=[`${p.dim("URL:")} ${a.url}`,`${p.dim("Provider:")} ${a.provider}`,`${p.dim("OS:")} ${a.os}`,`${p.dim("Name:")} ${a.name}`,`${p.dim("Runners:")} ${f.length}/${a.numberOfMachines} created, ${p.green(`${g} running`)}`];if(a.labels)h.push(`${p.dim("Labels:")} ${a.labels}`);let l=u?`${t} ${p.dim("(default)")}`:t;sr(h.join(`
|
|
97
|
+
`),l)}w.info(p.dim(`${o.length} profile(s)`))}}import{rm as We}from"fs/promises";import{join as Je}from"path";var Ae=G({name:{description:"Profile name to remove"}});class Gn extends I{name="remove";description="Remove a profile";positionals=Ae;async execute(r){let n=r.interactive?await Q(r.config):r.positionals.name;if(!n)throw new v("Profile name is required","Usage: hydra profile remove <name>");let{profile:o}=J(r.config,n),i=r.config.get("runners")??[],e=i.filter((c)=>c.profile===n);if(e.length>0){if(!await br({initialValue:!0,message:`This will stop and remove ${e.length} runner(s). Continue?`}))return;await this.removeRunners(o,e.map((d)=>d.id));let f=i.filter((d)=>d.profile!==n);r.config.set("runners",f)}let{[n]:t,...a}=r.config.get("profiles");if(r.config.set("profiles",a),r.config.get("defaultProfile")===n){let c=Object.keys(a);r.config.set("defaultProfile",c[0])}w.info(`${p.green("Removed")} profile "${n}".`)}async removeRunners(r,n){let o=z(r),i=Y();for(let e of n)i.start(`Stopping and removing ${e}...`),await o.stop([e]),await o.remove([e]),await We(Je(r.directory,e),{force:!0,recursive:!0}),i.stop(`${p.red("-")} ${e}`)}}class Sr extends I{name="profile";description="Manage profiles";init(){this.registerSubcommands([new qn,new Gn,new Nn])}}import{rm as Ke}from"fs/promises";import{join as Ye}from"path";var Ze=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class Br extends I{name="remove";description="Deregister and remove runners";positionals=Ze;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),i=r.config.get("runners")??[],e=i.filter((f)=>f.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=r.interactive?await this.promptRunnerSelection(e.map((f)=>f.id)):ur(r.positionals.ids??[],e.map((f)=>f.id)),a=z(o),s=Y();for(let f of t)s.start(`Stopping and removing ${f}...`),await a.stop([f]),await a.remove([f]),await Ke(Ye(o.directory,f),{force:!0,recursive:!0}),s.stop(`${p.red("-")} ${f}`);let c=i.filter((f)=>!t.includes(f.id));r.config.set("runners",c),w.info(`${p.green("Removed")} ${t.length} runner(s).`)}async promptRunnerSelection(r){return ar({message:"Select runners to remove",options:r.map((n)=>({label:n,value:n})),required:!0})}}var xe=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class _r extends I{name="start";description="Start runners";positionals=xe;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),e=(r.config.get("runners")??[]).filter((u)=>u.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=z(o),a=Y();a.start("Fetching runner status...");let s=await t.list();a.stop("Runner status fetched");let c=new Set(s.filter((u)=>u.status==="running").map((u)=>u.id)),f=e.map((u)=>u.id).filter((u)=>!c.has(u)),d=r.interactive?await this.promptRunnerSelection(f):ur(r.positionals.ids??[],e.map((u)=>u.id)),g=0;for(let u of d){if(c.has(u)){a.start(""),a.stop(`${p.dim("\u25CF")} ${u} ${p.dim("already running")}`);continue}a.start(`Starting ${u}...`),await t.start([u]),a.stop(`${p.green("\u25B6")} ${u}`),g++}w.info(`${p.green("Started")} ${g} runner(s).`)}async promptRunnerSelection(r){if(r.length===0)throw new v("All runners are already running");return ar({message:"Select runners to start",options:r.map((n)=>({label:n,value:n})),required:!0})}}var Qe={registered:p.yellow,running:p.green,stopped:p.red,unknown:p.dim};class Tr extends I{name="status";description="Show runner status across all profiles";async execute(r){let n=r.config.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=r.config.get("runners")??[],e=0,t=0,a=[];for(let s of o){let c=n[s],d=await z(c).list();if(a.length>0)a.push("");a.push(`${p.bold(s)} ${p.dim(c.url)}`);let g=new Set(i.filter((h)=>h.profile===s).map((h)=>h.id)),u=d.filter((h)=>g.has(h.id)).sort((h,l)=>h.name.localeCompare(l.name,void 0,{numeric:!0}));this.formatRunners(u,a),e+=u.length,t+=u.filter((h)=>h.status==="running").length}a.push(""),a.push(p.dim(`${e} runner(s) total, ${t} running`)),w.info(a.join(`
|
|
98
|
+
`))}formatRunners(r,n){if(r.length===0){n.push(p.dim(" No runners."));return}for(let o of r){let i=Qe[o.status]??p.dim,e=o.pid?p.dim(` (pid: ${o.pid})`):"";n.push(` ${i("\u25CF")} ${o.name} ${i(o.status)}${e}`)}}}var Xe=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class rn extends I{name="stop";description="Stop runners";positionals=Xe;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),e=(r.config.get("runners")??[]).filter((u)=>u.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=z(o),a=Y();a.start("Fetching runner status...");let s=await t.list();a.stop("Runner status fetched");let c=new Set(s.filter((u)=>u.status==="running").map((u)=>u.id)),f=e.map((u)=>u.id).filter((u)=>c.has(u)),d=r.interactive?await this.promptRunnerSelection(f):ur(r.positionals.ids??[],e.map((u)=>u.id)),g=0;for(let u of d){if(!c.has(u)){a.start(""),a.stop(`${p.dim("\u25CF")} ${u} ${p.dim("not running")}`);continue}a.start(`Stopping ${u}...`),await t.stop([u]),a.stop(`${p.red("\u25A0")} ${u}`),g++}w.info(`${p.green("Stopped")} ${g} runner(s).`)}async promptRunnerSelection(r){if(r.length===0)throw new v("No runners are currently running");return ar({message:"Select runners to stop",options:r.map((n)=>({label:n,value:n})),required:!0})}}class nn extends I{name="update";description="Update runners to the latest version";async execute(r){let n=r.config.get("profiles"),o=r.config.get("runners")??[];if(o.length===0)throw new v("No runners found","Run hydra create to provision runners");let i=Y(),e=Map.groupBy(o,(c)=>c.profile),t=null,a="",s=!1;for(let[c,f]of e){let d=n[c],g=f[0];if(!d||!g)continue;let u=z(d);if(!s){if(s=!0,i.start("Checking for updates..."),a=(await u.download()).version,t=await u.currentVersion(g.id),i.stop(`Current: v${t??"unknown"} | Latest: v${a}`),t===a){w.info(`Already on latest version ${p.dim(`(v${a})`)}`);return}}let h=await u.list(),l=new Set(h.filter((b)=>b.status==="running").map((b)=>b.id));for(let b of f){let k=l.has(b.id);if(i.start(`Updating ${b.id}...`),k)await u.stop([b.id]);if(await u.update([b.id]),k)await u.start([b.id]);let R=k?` ${p.dim("(restarted)")}`:"";i.stop(`${p.green("\u2713")} ${b.id}${R}`)}}w.info(`${p.green("Updated")} ${o.length} runner(s) from v${t} to v${a}`)}}class Oo extends yn{constructor(){super(new Ln(No,qo),{bin:Zr,clearOnStart:!0,exitLabel:"Exit",goodbyeMessage:"Heads down.",name:"HYDRA",promptMessage:"What do you need?",version:Eo})}init(){this.registerCommands([new Vr,new Xr,new _r,new rn,new Tr,new Or,new Br,new nn,new Sr])}}var Ve=new Oo;Ve.run();
|