@r5n/hydra 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -15
- package/dist/bundle-report.json +21 -0
- package/dist/cli.js +101 -319
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
<img src="https://avatars.githubusercontent.com/u/99986752?s=400&v=4" alt="R5N Labs" width="100" height="100">
|
|
4
4
|
</a>
|
|
5
5
|
|
|
6
|
+
<p><strong>The GitHub Runner Manager That Actually Scales 🚀</strong></p>
|
|
7
|
+
<p><em>🏊 Made for developers who'd rather be coding than configuring</em></p>
|
|
8
|
+
|
|
6
9
|
<h1>Hydra</h1>
|
|
7
|
-
<p><strong>GitHub Self-Hosted Runner Manager</strong></p>
|
|
8
10
|
|
|
9
11
|
<p>
|
|
10
12
|
<a href="https://www.npmjs.com/package/@r5n/hydra">
|
|
@@ -21,15 +23,71 @@
|
|
|
21
23
|
|
|
22
24
|
## Overview
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Tired of manually setting up GitHub Actions runners? Hydra transforms hours of tedious work into a single command. Create, manage, and monitor dozens of self-hosted runners with the simplicity you've been craving.
|
|
25
27
|
|
|
26
|
-
### ✨
|
|
28
|
+
### ✨ Why Hydra?
|
|
27
29
|
|
|
28
|
-
- 🚀 **
|
|
29
|
-
- 🔧 **
|
|
30
|
-
- 📊 **
|
|
31
|
-
- 🏃 **
|
|
32
|
-
- 🎯 **
|
|
30
|
+
- 🚀 **Lightning Fast** - Create 20 runners in the time it takes to manually create 1
|
|
31
|
+
- 🔧 **Smart Profiles** - Define once, deploy anywhere with reusable configs
|
|
32
|
+
- 📊 **Live Insights** - See exactly what your runners are doing in real-time
|
|
33
|
+
- 🏃 **73KB of Pure Speed** - Installs before your coffee finishes brewing
|
|
34
|
+
- 🎯 **Works Everywhere** - macOS, Linux, Windows - we've got you covered
|
|
35
|
+
|
|
36
|
+
## 🎯 What Can You Do?
|
|
37
|
+
|
|
38
|
+
<details>
|
|
39
|
+
<summary><strong>Create a fleet of runners in seconds</strong></summary>
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
$ hydra create -t $TOKEN -u https://github.com/myorg/repo -m 10 -l "gpu,docker"
|
|
43
|
+
⠋ Downloading runner package... (2.1s)
|
|
44
|
+
✔ Created runner gpu-runner-1
|
|
45
|
+
✔ Created runner gpu-runner-2
|
|
46
|
+
✔ Created runner gpu-runner-3
|
|
47
|
+
✔ Created runner gpu-runner-4
|
|
48
|
+
✔ Created runner gpu-runner-5
|
|
49
|
+
✔ Created runner gpu-runner-6
|
|
50
|
+
✔ Created runner gpu-runner-7
|
|
51
|
+
✔ Created runner gpu-runner-8
|
|
52
|
+
✔ Created runner gpu-runner-9
|
|
53
|
+
✔ Created runner gpu-runner-10
|
|
54
|
+
✅ All 10 runners created successfully in 8.3s
|
|
55
|
+
```
|
|
56
|
+
</details>
|
|
57
|
+
|
|
58
|
+
<details>
|
|
59
|
+
<summary><strong>Monitor your runner army</strong></summary>
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
$ hydra status -p production
|
|
63
|
+
┌─────────────────┬─────────┬───────────┬──────────────┐
|
|
64
|
+
│ Name │ Status │ Busy │ Labels │
|
|
65
|
+
├─────────────────┼─────────┼───────────┼──────────────┤
|
|
66
|
+
│ prod-runner-1 │ ✅ Idle │ No │ linux,docker │
|
|
67
|
+
│ prod-runner-2 │ ✅ Idle │ No │ linux,docker │
|
|
68
|
+
│ prod-runner-3 │ 🔄 Busy │ Yes (2m) │ linux,docker │
|
|
69
|
+
│ prod-runner-4 │ ✅ Idle │ No │ linux,docker │
|
|
70
|
+
│ prod-runner-5 │ ❌ Offline │ - │ linux,docker │
|
|
71
|
+
└─────────────────┴─────────┴───────────┴──────────────┘
|
|
72
|
+
Summary: 3 idle, 1 busy, 1 offline
|
|
73
|
+
```
|
|
74
|
+
</details>
|
|
75
|
+
|
|
76
|
+
<details>
|
|
77
|
+
<summary><strong>Monitor runner status</strong></summary>
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
$ hydra status -p production
|
|
81
|
+
🔍 Checking runner status...
|
|
82
|
+
✅ Runner 1: Online (idle)
|
|
83
|
+
✅ Runner 2: Online (busy - job #1234)
|
|
84
|
+
✅ Runner 3: Online (idle)
|
|
85
|
+
✓ Created runner-4
|
|
86
|
+
✓ Created runner-5
|
|
87
|
+
|
|
88
|
+
🔍 Monitoring continues... (press Ctrl+C to stop)
|
|
89
|
+
```
|
|
90
|
+
</details>
|
|
33
91
|
|
|
34
92
|
## 📦 Installation
|
|
35
93
|
|
|
@@ -147,9 +205,9 @@ hydra create --help
|
|
|
147
205
|
|
|
148
206
|
## 🔧 Configuration
|
|
149
207
|
|
|
150
|
-
###
|
|
208
|
+
### The Magic of Profiles 🎭
|
|
151
209
|
|
|
152
|
-
|
|
210
|
+
Stop typing the same commands over and over. Profiles let you define your runner configurations once and reuse them everywhere:
|
|
153
211
|
|
|
154
212
|
#### Example: `hydra.json`
|
|
155
213
|
|
|
@@ -291,7 +349,7 @@ fi
|
|
|
291
349
|
# Run with debug logging
|
|
292
350
|
DEBUG=* hydra create -t TOKEN -u URL
|
|
293
351
|
|
|
294
|
-
# Check runner
|
|
352
|
+
# Check runner diagnostics (if needed)
|
|
295
353
|
cat ./gh-runners/machines/1/_diag/*.log
|
|
296
354
|
```
|
|
297
355
|
|
|
@@ -304,7 +362,3 @@ Contributions are welcome! Please see the [main repository](https://github.com/r
|
|
|
304
362
|
Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details.
|
|
305
363
|
|
|
306
364
|
---
|
|
307
|
-
|
|
308
|
-
<div align="center">
|
|
309
|
-
Built with ❤️ by <a href="https://github.com/r5n-labs">R5N Labs</a>
|
|
310
|
-
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"timestamp": "2025-08-08T08:44:29.933Z",
|
|
3
|
+
"analysis": {
|
|
4
|
+
"totalSize": 138600,
|
|
5
|
+
"totalSizeKB": 135.3515625,
|
|
6
|
+
"totalSizeMB": 0.13217926025390625,
|
|
7
|
+
"files": [
|
|
8
|
+
{
|
|
9
|
+
"file": "dist/cli.js",
|
|
10
|
+
"size": 138600,
|
|
11
|
+
"sizeKB": 135.3515625,
|
|
12
|
+
"sizeMB": 0.13217926025390625
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"warnings": []
|
|
16
|
+
},
|
|
17
|
+
"threshold": {
|
|
18
|
+
"maxSizeMB": 1,
|
|
19
|
+
"exceeded": false
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -1,322 +1,104 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
var Lo=Object.create;var{getPrototypeOf:No,defineProperty:ht,getOwnPropertyNames:Go}=Object;var Ao=Object.prototype.hasOwnProperty;var $n=(n,o,r)=>{r=n!=null?Lo(No(n)):{};let e=o||!n||!n.__esModule?ht(r,"default",{value:n,enumerable:!0}):r;for(let i of Go(n))if(!Ao.call(e,i))ht(e,i,{get:()=>n[i],enumerable:!0});return e};var bt=(n,o)=>()=>(o||n((o={exports:{}}).exports,o),o.exports);var In=bt((Je,yt)=>{var Wn={to(n,o){if(!o)return`\x1B[${n+1}G`;return`\x1B[${o+1};${n+1}H`},move(n,o){let r="";if(n<0)r+=`\x1B[${-n}D`;else if(n>0)r+=`\x1B[${n}C`;if(o<0)r+=`\x1B[${-o}A`;else if(o>0)r+=`\x1B[${o}B`;return r},up:(n=1)=>`\x1B[${n}A`,down:(n=1)=>`\x1B[${n}B`,forward:(n=1)=>`\x1B[${n}C`,backward:(n=1)=>`\x1B[${n}D`,nextLine:(n=1)=>"\x1B[E".repeat(n),prevLine:(n=1)=>"\x1B[F".repeat(n),left:"\x1B[G",hide:"\x1B[?25l",show:"\x1B[?25h",save:"\x1B7",restore:"\x1B8"},Xo={up:(n=1)=>"\x1B[S".repeat(n),down:(n=1)=>"\x1B[T".repeat(n)},_o={screen:"\x1B[2J",up:(n=1)=>"\x1B[1J".repeat(n),down:(n=1)=>"\x1B[J".repeat(n),line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",lines(n){let o="";for(let r=0;r<n;r++)o+=this.line+(r<n-1?Wn.up():"");if(n)o+=Wn.left;return o}};yt.exports={cursor:Wn,scroll:Xo,erase:_o,beep:"\x07"}});var zn=bt((Ye,Kn)=>{var On=process||{},wt=On.argv||[],En=On.env||{},Uo=!(!!En.NO_COLOR||wt.includes("--no-color"))&&(!!En.FORCE_COLOR||wt.includes("--color")||On.platform==="win32"||(On.stdout||{}).isTTY&&En.TERM!=="dumb"||!!En.CI),qo=(n,o,r=n)=>(e)=>{let i=""+e,s=i.indexOf(o,n.length);return~s?n+Co(i,o,r,s)+o:n+i+o},Co=(n,o,r,e)=>{let i="",s=0;do i+=n.substring(s,e)+r,s=e+o.length,e=n.indexOf(o,s);while(~e);return i+n.substring(s)},xt=(n=Uo)=>{let o=n?qo:()=>String;return{isColorSupported:n,reset:o("\x1B[0m","\x1B[0m"),bold:o("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:o("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:o("\x1B[3m","\x1B[23m"),underline:o("\x1B[4m","\x1B[24m"),inverse:o("\x1B[7m","\x1B[27m"),hidden:o("\x1B[8m","\x1B[28m"),strikethrough:o("\x1B[9m","\x1B[29m"),black:o("\x1B[30m","\x1B[39m"),red:o("\x1B[31m","\x1B[39m"),green:o("\x1B[32m","\x1B[39m"),yellow:o("\x1B[33m","\x1B[39m"),blue:o("\x1B[34m","\x1B[39m"),magenta:o("\x1B[35m","\x1B[39m"),cyan:o("\x1B[36m","\x1B[39m"),white:o("\x1B[37m","\x1B[39m"),gray:o("\x1B[90m","\x1B[39m"),bgBlack:o("\x1B[40m","\x1B[49m"),bgRed:o("\x1B[41m","\x1B[49m"),bgGreen:o("\x1B[42m","\x1B[49m"),bgYellow:o("\x1B[43m","\x1B[49m"),bgBlue:o("\x1B[44m","\x1B[49m"),bgMagenta:o("\x1B[45m","\x1B[49m"),bgCyan:o("\x1B[46m","\x1B[49m"),bgWhite:o("\x1B[47m","\x1B[49m"),blackBright:o("\x1B[90m","\x1B[39m"),redBright:o("\x1B[91m","\x1B[39m"),greenBright:o("\x1B[92m","\x1B[39m"),yellowBright:o("\x1B[93m","\x1B[39m"),blueBright:o("\x1B[94m","\x1B[39m"),magentaBright:o("\x1B[95m","\x1B[39m"),cyanBright:o("\x1B[96m","\x1B[39m"),whiteBright:o("\x1B[97m","\x1B[39m"),bgBlackBright:o("\x1B[100m","\x1B[49m"),bgRedBright:o("\x1B[101m","\x1B[49m"),bgGreenBright:o("\x1B[102m","\x1B[49m"),bgYellowBright:o("\x1B[103m","\x1B[49m"),bgBlueBright:o("\x1B[104m","\x1B[49m"),bgMagentaBright:o("\x1B[105m","\x1B[49m"),bgCyanBright:o("\x1B[106m","\x1B[49m"),bgWhiteBright:o("\x1B[107m","\x1B[49m")}};Kn.exports=xt();Kn.exports.createColors=xt});var G=$n(In(),1),Xt=$n(zn(),1);import{stdin as Gt,stdout as At}from"process";import*as Q from"readline";import $t from"readline";import{Writable as vo}from"stream";function Ho({onlyFirst:n=!1}={}){let o=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");return new RegExp(o,n?void 0:"g")}var Po=Ho();function _t(n){if(typeof n!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof n}\``);return n.replace(Po,"")}function Ut(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var qt={exports:{}};(function(n){var o={};n.exports=o,o.eastAsianWidth=function(e){var i=e.charCodeAt(0),s=e.length==2?e.charCodeAt(1):0,t=i;return 55296<=i&&i<=56319&&56320<=s&&s<=57343&&(i&=1023,s&=1023,t=i<<10|s,t+=65536),t==12288||65281<=t&&t<=65376||65504<=t&&t<=65510?"F":t==8361||65377<=t&&t<=65470||65474<=t&&t<=65479||65482<=t&&t<=65487||65490<=t&&t<=65495||65498<=t&&t<=65500||65512<=t&&t<=65518?"H":4352<=t&&t<=4447||4515<=t&&t<=4519||4602<=t&&t<=4607||9001<=t&&t<=9002||11904<=t&&t<=11929||11931<=t&&t<=12019||12032<=t&&t<=12245||12272<=t&&t<=12283||12289<=t&&t<=12350||12353<=t&&t<=12438||12441<=t&&t<=12543||12549<=t&&t<=12589||12593<=t&&t<=12686||12688<=t&&t<=12730||12736<=t&&t<=12771||12784<=t&&t<=12830||12832<=t&&t<=12871||12880<=t&&t<=13054||13056<=t&&t<=19903||19968<=t&&t<=42124||42128<=t&&t<=42182||43360<=t&&t<=43388||44032<=t&&t<=55203||55216<=t&&t<=55238||55243<=t&&t<=55291||63744<=t&&t<=64255||65040<=t&&t<=65049||65072<=t&&t<=65106||65108<=t&&t<=65126||65128<=t&&t<=65131||110592<=t&&t<=110593||127488<=t&&t<=127490||127504<=t&&t<=127546||127552<=t&&t<=127560||127568<=t&&t<=127569||131072<=t&&t<=194367||177984<=t&&t<=196605||196608<=t&&t<=262141?"W":32<=t&&t<=126||162<=t&&t<=163||165<=t&&t<=166||t==172||t==175||10214<=t&&t<=10221||10629<=t&&t<=10630?"Na":t==161||t==164||167<=t&&t<=168||t==170||173<=t&&t<=174||176<=t&&t<=180||182<=t&&t<=186||188<=t&&t<=191||t==198||t==208||215<=t&&t<=216||222<=t&&t<=225||t==230||232<=t&&t<=234||236<=t&&t<=237||t==240||242<=t&&t<=243||247<=t&&t<=250||t==252||t==254||t==257||t==273||t==275||t==283||294<=t&&t<=295||t==299||305<=t&&t<=307||t==312||319<=t&&t<=322||t==324||328<=t&&t<=331||t==333||338<=t&&t<=339||358<=t&&t<=359||t==363||t==462||t==464||t==466||t==468||t==470||t==472||t==474||t==476||t==593||t==609||t==708||t==711||713<=t&&t<=715||t==717||t==720||728<=t&&t<=731||t==733||t==735||768<=t&&t<=879||913<=t&&t<=929||931<=t&&t<=937||945<=t&&t<=961||963<=t&&t<=969||t==1025||1040<=t&&t<=1103||t==1105||t==8208||8211<=t&&t<=8214||8216<=t&&t<=8217||8220<=t&&t<=8221||8224<=t&&t<=8226||8228<=t&&t<=8231||t==8240||8242<=t&&t<=8243||t==8245||t==8251||t==8254||t==8308||t==8319||8321<=t&&t<=8324||t==8364||t==8451||t==8453||t==8457||t==8467||t==8470||8481<=t&&t<=8482||t==8486||t==8491||8531<=t&&t<=8532||8539<=t&&t<=8542||8544<=t&&t<=8555||8560<=t&&t<=8569||t==8585||8592<=t&&t<=8601||8632<=t&&t<=8633||t==8658||t==8660||t==8679||t==8704||8706<=t&&t<=8707||8711<=t&&t<=8712||t==8715||t==8719||t==8721||t==8725||t==8730||8733<=t&&t<=8736||t==8739||t==8741||8743<=t&&t<=8748||t==8750||8756<=t&&t<=8759||8764<=t&&t<=8765||t==8776||t==8780||t==8786||8800<=t&&t<=8801||8804<=t&&t<=8807||8810<=t&&t<=8811||8814<=t&&t<=8815||8834<=t&&t<=8835||8838<=t&&t<=8839||t==8853||t==8857||t==8869||t==8895||t==8978||9312<=t&&t<=9449||9451<=t&&t<=9547||9552<=t&&t<=9587||9600<=t&&t<=9615||9618<=t&&t<=9621||9632<=t&&t<=9633||9635<=t&&t<=9641||9650<=t&&t<=9651||9654<=t&&t<=9655||9660<=t&&t<=9661||9664<=t&&t<=9665||9670<=t&&t<=9672||t==9675||9678<=t&&t<=9681||9698<=t&&t<=9701||t==9711||9733<=t&&t<=9734||t==9737||9742<=t&&t<=9743||9748<=t&&t<=9749||t==9756||t==9758||t==9792||t==9794||9824<=t&&t<=9825||9827<=t&&t<=9829||9831<=t&&t<=9834||9836<=t&&t<=9837||t==9839||9886<=t&&t<=9887||9918<=t&&t<=9919||9924<=t&&t<=9933||9935<=t&&t<=9953||t==9955||9960<=t&&t<=9983||t==10045||t==10071||10102<=t&&t<=10111||11093<=t&&t<=11097||12872<=t&&t<=12879||57344<=t&&t<=63743||65024<=t&&t<=65039||t==65533||127232<=t&&t<=127242||127248<=t&&t<=127277||127280<=t&&t<=127337||127344<=t&&t<=127386||917760<=t&&t<=917999||983040<=t&&t<=1048573||1048576<=t&&t<=1114109?"A":"N"},o.characterLength=function(e){var i=this.eastAsianWidth(e);return i=="F"||i=="W"||i=="A"?2:1};function r(e){return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}o.length=function(e){for(var i=r(e),s=0,t=0;t<i.length;t++)s=s+this.characterLength(i[t]);return s},o.slice=function(e,i,s){textLen=o.length(e),i=i||0,s=s||1,i<0&&(i=textLen+i),s<0&&(s=textLen+s);for(var t="",f=0,a=r(e),c=0;c<a.length;c++){var m=a[c],l=o.length(m);if(f>=i-(l==2?1:0))if(f+l<=s)t+=m;else break;f+=l}return t}})(qt);var Mo=qt.exports,Bo=Ut(Mo),Wo=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g},Io=Ut(Wo);function dn(n,o={}){if(typeof n!="string"||n.length===0||(o={ambiguousIsNarrow:!0,...o},n=_t(n),n.length===0))return 0;n=n.replace(Io()," ");let r=o.ambiguousIsNarrow?1:2,e=0;for(let i of n){let s=i.codePointAt(0);if(s<=31||s>=127&&s<=159||s>=768&&s<=879)continue;switch(Bo.eastAsianWidth(i)){case"F":case"W":e+=2;break;case"A":e+=r;break;default:e+=1}}return e}var kn=10,Et=(n=0)=>(o)=>`\x1B[${o+n}m`,Ot=(n=0)=>(o)=>`\x1B[${38+n};5;${o}m`,Rt=(n=0)=>(o,r,e)=>`\x1B[${38+n};2;${o};${r};${e}m`,O={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(O.modifier);var Ko=Object.keys(O.color),zo=Object.keys(O.bgColor);[...Ko];function ko(){let n=new Map;for(let[o,r]of Object.entries(O)){for(let[e,i]of Object.entries(r))O[e]={open:`\x1B[${i[0]}m`,close:`\x1B[${i[1]}m`},r[e]=O[e],n.set(i[0],i[1]);Object.defineProperty(O,o,{value:r,enumerable:!1})}return Object.defineProperty(O,"codes",{value:n,enumerable:!1}),O.color.close="\x1B[39m",O.bgColor.close="\x1B[49m",O.color.ansi=Et(),O.color.ansi256=Ot(),O.color.ansi16m=Rt(),O.bgColor.ansi=Et(kn),O.bgColor.ansi256=Ot(kn),O.bgColor.ansi16m=Rt(kn),Object.defineProperties(O,{rgbToAnsi256:{value:(o,r,e)=>o===r&&r===e?o<8?16:o>248?231:Math.round((o-8)/247*24)+232:16+36*Math.round(o/255*5)+6*Math.round(r/255*5)+Math.round(e/255*5),enumerable:!1},hexToRgb:{value:(o)=>{let r=/[a-f\d]{6}|[a-f\d]{3}/i.exec(o.toString(16));if(!r)return[0,0,0];let[e]=r;e.length===3&&(e=[...e].map((s)=>s+s).join(""));let i=Number.parseInt(e,16);return[i>>16&255,i>>8&255,i&255]},enumerable:!1},hexToAnsi256:{value:(o)=>O.rgbToAnsi256(...O.hexToRgb(o)),enumerable:!1},ansi256ToAnsi:{value:(o)=>{if(o<8)return 30+o;if(o<16)return 90+(o-8);let r,e,i;if(o>=232)r=((o-232)*10+8)/255,e=r,i=r;else{o-=16;let f=o%36;r=Math.floor(o/36)/5,e=Math.floor(f/6)/5,i=f%6/5}let s=Math.max(r,e,i)*2;if(s===0)return 30;let t=30+(Math.round(i)<<2|Math.round(e)<<1|Math.round(r));return s===2&&(t+=60),t},enumerable:!1},rgbToAnsi:{value:(o,r,e)=>O.ansi256ToAnsi(O.rgbToAnsi256(o,r,e)),enumerable:!1},hexToAnsi:{value:(o)=>O.ansi256ToAnsi(O.hexToAnsi256(o)),enumerable:!1}}),O}var Jo=ko(),Tn=new Set(["\x1B","\x9B"]),Yo=39,jn="\x07",Ct="[",jo="]",vt="m",Zn=`${jo}8;;`,St=(n)=>`${Tn.values().next().value}${Ct}${n}${vt}`,Tt=(n)=>`${Tn.values().next().value}${Zn}${n}${jn}`,Zo=(n)=>n.split(" ").map((o)=>dn(o)),Jn=(n,o,r)=>{let e=[...o],i=!1,s=!1,t=dn(_t(n[n.length-1]));for(let[f,a]of e.entries()){let c=dn(a);if(t+c<=r?n[n.length-1]+=a:(n.push(a),t=0),Tn.has(a)&&(i=!0,s=e.slice(f+1).join("").startsWith(Zn)),i){s?a===jn&&(i=!1,s=!1):a===vt&&(i=!1);continue}t+=c,t===r&&f<e.length-1&&(n.push(""),t=0)}!t&&n[n.length-1].length>0&&n.length>1&&(n[n.length-2]+=n.pop())},Qo=(n)=>{let o=n.split(" "),r=o.length;for(;r>0&&!(dn(o[r-1])>0);)r--;return r===o.length?n:o.slice(0,r).join(" ")+o.slice(r).join("")},Vo=(n,o,r={})=>{if(r.trim!==!1&&n.trim()==="")return"";let e="",i,s,t=Zo(n),f=[""];for(let[c,m]of n.split(" ").entries()){r.trim!==!1&&(f[f.length-1]=f[f.length-1].trimStart());let l=dn(f[f.length-1]);if(c!==0&&(l>=o&&(r.wordWrap===!1||r.trim===!1)&&(f.push(""),l=0),(l>0||r.trim===!1)&&(f[f.length-1]+=" ",l++)),r.hard&&t[c]>o){let u=o-l,b=1+Math.floor((t[c]-u-1)/o);Math.floor((t[c]-1)/o)<b&&f.push(""),Jn(f,m,o);continue}if(l+t[c]>o&&l>0&&t[c]>0){if(r.wordWrap===!1&&l<o){Jn(f,m,o);continue}f.push("")}if(l+t[c]>o&&r.wordWrap===!1){Jn(f,m,o);continue}f[f.length-1]+=m}r.trim!==!1&&(f=f.map((c)=>Qo(c)));let a=[...f.join(`
|
|
3
|
-
`)];
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
var jt=Object.create;var{getPrototypeOf:Vt,defineProperty:wn,getOwnPropertyNames:Kt}=Object;var Zt=Object.prototype.hasOwnProperty;var cr=(r,n,t)=>{t=r!=null?jt(Vt(r)):{};let o=n||!r||!r.__esModule?wn(t,"default",{value:r,enumerable:!0}):t;for(let e of Kt(r))if(!Zt.call(o,e))wn(o,e,{get:()=>r[e],enumerable:!0});return o};var bn=(r,n)=>()=>(n||r((n={exports:{}}).exports,n),n.exports);var zt=import.meta.require;var Lr=bn((He,_n)=>{var Pr={to(r,n){if(!n)return`\x1B[${r+1}G`;return`\x1B[${n+1};${r+1}H`},move(r,n){let t="";if(r<0)t+=`\x1B[${-r}D`;else if(r>0)t+=`\x1B[${r}C`;if(n<0)t+=`\x1B[${-n}A`;else if(n>0)t+=`\x1B[${n}B`;return t},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"},ti={up:(r=1)=>"\x1B[S".repeat(r),down:(r=1)=>"\x1B[T".repeat(r)},ii={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 t=0;t<r;t++)n+=this.line+(t<r-1?Pr.up():"");if(r)n+=Pr.left;return n}};_n.exports={cursor:Pr,scroll:ti,erase:ii,beep:"\x07"}});var Br=bn((Se,qr)=>{var Er=process||{},On=Er.argv||[],br=Er.env||{},oi=!(!!br.NO_COLOR||On.includes("--no-color"))&&(!!br.FORCE_COLOR||On.includes("--color")||Er.platform==="win32"||(Er.stdout||{}).isTTY&&br.TERM!=="dumb"||!!br.CI),ei=(r,n,t=r)=>(o)=>{let e=""+o,s=e.indexOf(n,r.length);return~s?r+si(e,n,t,s)+n:r+e+n},si=(r,n,t,o)=>{let e="",s=0;do e+=r.substring(s,o)+t,s=o+n.length,o=r.indexOf(n,s);while(~o);return e+r.substring(s)},kn=(r=oi)=>{let n=r?ei:()=>String;return{isColorSupported:r,reset:n("\x1B[0m","\x1B[0m"),bold:n("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:n("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:n("\x1B[3m","\x1B[23m"),underline:n("\x1B[4m","\x1B[24m"),inverse:n("\x1B[7m","\x1B[27m"),hidden:n("\x1B[8m","\x1B[28m"),strikethrough:n("\x1B[9m","\x1B[29m"),black:n("\x1B[30m","\x1B[39m"),red:n("\x1B[31m","\x1B[39m"),green:n("\x1B[32m","\x1B[39m"),yellow:n("\x1B[33m","\x1B[39m"),blue:n("\x1B[34m","\x1B[39m"),magenta:n("\x1B[35m","\x1B[39m"),cyan:n("\x1B[36m","\x1B[39m"),white:n("\x1B[37m","\x1B[39m"),gray:n("\x1B[90m","\x1B[39m"),bgBlack:n("\x1B[40m","\x1B[49m"),bgRed:n("\x1B[41m","\x1B[49m"),bgGreen:n("\x1B[42m","\x1B[49m"),bgYellow:n("\x1B[43m","\x1B[49m"),bgBlue:n("\x1B[44m","\x1B[49m"),bgMagenta:n("\x1B[45m","\x1B[49m"),bgCyan:n("\x1B[46m","\x1B[49m"),bgWhite:n("\x1B[47m","\x1B[49m"),blackBright:n("\x1B[90m","\x1B[39m"),redBright:n("\x1B[91m","\x1B[39m"),greenBright:n("\x1B[92m","\x1B[39m"),yellowBright:n("\x1B[93m","\x1B[39m"),blueBright:n("\x1B[94m","\x1B[39m"),magentaBright:n("\x1B[95m","\x1B[39m"),cyanBright:n("\x1B[96m","\x1B[39m"),whiteBright:n("\x1B[97m","\x1B[39m"),bgBlackBright:n("\x1B[100m","\x1B[49m"),bgRedBright:n("\x1B[101m","\x1B[49m"),bgGreenBright:n("\x1B[102m","\x1B[49m"),bgYellowBright:n("\x1B[103m","\x1B[49m"),bgBlueBright:n("\x1B[104m","\x1B[49m"),bgMagentaBright:n("\x1B[105m","\x1B[49m"),bgCyanBright:n("\x1B[106m","\x1B[49m"),bgWhiteBright:n("\x1B[107m","\x1B[49m")}};qr.exports=kn();qr.exports.createColors=kn});var wr="0.5.2";class mr extends Error{code;severity;context;originalError;timestamp;recoveryStrategy;constructor(r,n,t="medium",o={},e){super(r);if(this.name="HydraError",this.code=n,this.severity=t,this.context=o,this.originalError=e,this.timestamp=new Date,this.recoveryStrategy=w.getRecoveryStrategy(n),e&&e.stack)this.stack=`${this.stack}
|
|
3
|
+
Caused by: ${e.stack}`}toJSON(){return{name:this.name,message:this.message,code:this.code,severity:this.severity,context:this.context,timestamp:this.timestamp.toISOString(),recoveryStrategy:this.recoveryStrategy,originalError:this.originalError?.message}}}class w{static instance=null;errorHistory=[];maxHistorySize=100;constructor(){}static getInstance(){if(!w.instance)w.instance=new w;return w.instance}static getRecoveryStrategy(r){switch(r){case"NETWORK_ERROR":return{canRecover:!0,retryable:!0,maxRetries:3,retryDelay:2000,recoveryAction:"retry_with_backoff",userAction:"Check your network connection and try again"};case"CONFIG_ERROR":return{canRecover:!0,retryable:!1,userAction:"Fix the configuration file and try again. Use 'hydra validate' to check your config"};case"VALIDATION_ERROR":return{canRecover:!0,retryable:!1,userAction:"Correct the validation errors and try again"};case"FILE_SYSTEM_ERROR":return{canRecover:!0,retryable:!1,userAction:"Check file permissions and disk space, then try again"};case"AUTHENTICATION_ERROR":return{canRecover:!0,retryable:!1,userAction:"Check your GitHub token and repository permissions"};case"WORKER_ERROR":return{canRecover:!0,retryable:!0,maxRetries:2,retryDelay:1000,recoveryAction:"restart_worker",userAction:"Worker will be restarted automatically"};case"GITHUB_API_ERROR":return{canRecover:!0,retryable:!0,maxRetries:3,retryDelay:5000,recoveryAction:"retry_with_exponential_backoff",userAction:"GitHub API rate limit may be exceeded. Please wait and try again"};case"TEMPLATE_ERROR":return{canRecover:!0,retryable:!1,userAction:"Check template syntax and dependencies, then try again"};case"MIGRATION_ERROR":return{canRecover:!1,retryable:!1,userAction:"Manual intervention required. Check migration logs and contact support"};case"RUNNER_ERROR":return{canRecover:!0,retryable:!0,maxRetries:2,retryDelay:3000,recoveryAction:"recreate_runner",userAction:"Runner will be recreated automatically"};case"PERMISSION_ERROR":return{canRecover:!0,retryable:!1,userAction:"Check file/directory permissions and run with appropriate privileges"};case"DEPENDENCY_ERROR":return{canRecover:!0,retryable:!1,userAction:"Install missing dependencies and try again"};case"COMMAND_ERROR":return{canRecover:!0,retryable:!1,userAction:"Check command syntax and arguments, then try again"};default:return{canRecover:!1,retryable:!1,userAction:"An unexpected error occurred. Please report this issue"}}}static createError(r,n,t="medium",o={},e){return new mr(r,n,t,o,e)}static handleError(r,n={}){let t=w.getInstance();if(r instanceof mr)return t.recordError(r),r;let o;if(r instanceof Error){let e=w.classifyError(r),s=w.getSeverityFromCode(e);o=new mr(r.message,e,s,n,r)}else o=new mr(String(r),"UNKNOWN_ERROR","medium",n);return t.recordError(o),o}static classifyError(r){let n=r.message.toLowerCase(),t=r.stack?.toLowerCase()||"";if(n.includes("network")||n.includes("connection")||n.includes("timeout"))return"NETWORK_ERROR";if(n.includes("config")||n.includes("configuration"))return"CONFIG_ERROR";if(n.includes("validation")||n.includes("invalid")||n.includes("schema"))return"VALIDATION_ERROR";if(n.includes("enoent")||n.includes("permission")||n.includes("access denied"))return"FILE_SYSTEM_ERROR";if(n.includes("auth")||n.includes("token")||n.includes("unauthorized"))return"AUTHENTICATION_ERROR";if(n.includes("worker")||t.includes("worker"))return"WORKER_ERROR";if(n.includes("github")||n.includes("api")||n.includes("rate limit"))return"GITHUB_API_ERROR";if(n.includes("template"))return"TEMPLATE_ERROR";if(n.includes("migration")||n.includes("migrate"))return"MIGRATION_ERROR";if(n.includes("runner"))return"RUNNER_ERROR";if(n.includes("permission")||n.includes("eperm"))return"PERMISSION_ERROR";if(n.includes("dependency")||n.includes("missing")||n.includes("not found"))return"DEPENDENCY_ERROR";if(n.includes("command")||n.includes("unknown"))return"COMMAND_ERROR";return"UNKNOWN_ERROR"}static getSeverityFromCode(r){switch(r){case"MIGRATION_ERROR":case"PERMISSION_ERROR":return"critical";case"AUTHENTICATION_ERROR":case"CONFIG_ERROR":case"DEPENDENCY_ERROR":return"high";case"NETWORK_ERROR":case"GITHUB_API_ERROR":case"WORKER_ERROR":case"RUNNER_ERROR":return"medium";default:return"low"}}static formatError(r){let{code:n,message:t,severity:o,context:e,recoveryStrategy:s}=r,i=`\u274C ${t}`;if(e.command)i+=`
|
|
4
|
+
Command: ${e.command}`;if(e.operation)i+=`
|
|
5
|
+
Operation: ${e.operation}`;if(e.profile)i+=`
|
|
6
|
+
Profile: ${e.profile}`;if(e.directory)i+=`
|
|
7
|
+
Directory: ${e.directory}`;if(e.machineIndex!==void 0)i+=`
|
|
8
|
+
Machine: ${e.machineIndex}`;if(i+=`
|
|
9
|
+
Code: ${n}`,i+=`
|
|
10
|
+
Severity: ${o.toUpperCase()}`,s.userAction)i+=`
|
|
11
|
+
|
|
12
|
+
\uD83D\uDCA1 ${s.userAction}`;return i}static formatDebugError(r){return JSON.stringify(r.toJSON(),null,2)}recordError(r){if(this.errorHistory.unshift(r),this.errorHistory.length>this.maxHistorySize)this.errorHistory=this.errorHistory.slice(0,this.maxHistorySize)}getErrorHistory(){return[...this.errorHistory]}getErrorStats(){return this.errorHistory.reduce((r,n)=>{return r[n.code]=(r[n.code]||0)+1,r},{})}clearHistory(){this.errorHistory=[]}}import{parseArgs as zi}from"util";import{performance as fr}from"perf_hooks";var Yt=!process.env.NO_COLOR&&(process.env.FORCE_COLOR||(process.stdout?.isTTY??!1)),Xt=["blue","cyan","gray","green","magenta","red","white","yellow"],Qt=["bold","dim","italic","underline","reset"],$n={bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",reset:"\x1B[0m",underline:"\x1B[4m"},En={"\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 Gr(r){return(n)=>Yt?`${r}${n}${$n.reset}`:n}function xn({bright:r=!1,color:n}){let t=Bun.color(n,"ansi");if(!t||typeof t!=="string")return"";return r&&t in En?En[t]:t}var Ft=Xt.reduce((r,n)=>{let t=xn({color:n});if(t)r[n]=Gr(t);let o=xn({bright:!0,color:n});if(o)r[`${n}Bright`]=Gr(o);return r},{}),Dt=Qt.reduce((r,n)=>{return r[n]=Gr($n[n]),r},{}),E={...Ft,...Dt};var ri=[{color:E.dim,console:console.log,label:"DEBUG",level:0,method:"debug"},{color:E.cyan,console:console.info,label:"INFO ",level:1,method:"info"},{color:E.yellow,console:console.warn,label:"WARN ",level:2,method:"warn"},{color:E.red,console:console.error,label:"ERROR",level:3,method:"error"}],k=({prefix:r="",level:n=process.env.DEBUG?0:1}={})=>{let t={};for(let o of ri)t[o.method]=n<=o.level?(...e)=>{let s=e.map((i)=>String(i??"")).join(" ");o.console(ni({level:o.color(o.label),message:s,prefix:r}))}:()=>{};return t.child=(o)=>k({level:n,prefix:`${r}:${o}`}),t},Ur=k();function ni({prefix:r,level:n,message:t}){let o="";try{let i=new Date().toISOString().split("T")[1];if(i)o=i.split(".")[0]||""}catch{o="00:00:00"}let e=r?`[${r}] `:"";return`${E.dim(o)} ${n} ${e}${t}`}var y={arrow:E.yellow,bold:E.bold,boolean:E.cyan,bullet:E.yellow,busy:E.yellow,command:E.green,dim:E.dim,error:E.red,flag:E.yellow,info:E.cyan,number:E.magenta,offline:E.red,online:E.green,separator:E.dim,string:E.green,success:E.green,value:E.cyan,warning:E.yellow};var I=cr(Lr(),1),Gn=cr(Br(),1);import{stdin as Wn,stdout as Mn}from"process";import*as V from"readline";import vn from"readline";import{Writable as ai}from"stream";function fi({onlyFirst:r=!1}={}){let n=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");return new RegExp(n,r?void 0:"g")}var di=fi();function Un(r){if(typeof r!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof r}\``);return r.replace(di,"")}function Pn(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var Ln={exports:{}};(function(r){var n={};r.exports=n,n.eastAsianWidth=function(o){var e=o.charCodeAt(0),s=o.length==2?o.charCodeAt(1):0,i=e;return 55296<=e&&e<=56319&&56320<=s&&s<=57343&&(e&=1023,s&=1023,i=e<<10|s,i+=65536),i==12288||65281<=i&&i<=65376||65504<=i&&i<=65510?"F":i==8361||65377<=i&&i<=65470||65474<=i&&i<=65479||65482<=i&&i<=65487||65490<=i&&i<=65495||65498<=i&&i<=65500||65512<=i&&i<=65518?"H":4352<=i&&i<=4447||4515<=i&&i<=4519||4602<=i&&i<=4607||9001<=i&&i<=9002||11904<=i&&i<=11929||11931<=i&&i<=12019||12032<=i&&i<=12245||12272<=i&&i<=12283||12289<=i&&i<=12350||12353<=i&&i<=12438||12441<=i&&i<=12543||12549<=i&&i<=12589||12593<=i&&i<=12686||12688<=i&&i<=12730||12736<=i&&i<=12771||12784<=i&&i<=12830||12832<=i&&i<=12871||12880<=i&&i<=13054||13056<=i&&i<=19903||19968<=i&&i<=42124||42128<=i&&i<=42182||43360<=i&&i<=43388||44032<=i&&i<=55203||55216<=i&&i<=55238||55243<=i&&i<=55291||63744<=i&&i<=64255||65040<=i&&i<=65049||65072<=i&&i<=65106||65108<=i&&i<=65126||65128<=i&&i<=65131||110592<=i&&i<=110593||127488<=i&&i<=127490||127504<=i&&i<=127546||127552<=i&&i<=127560||127568<=i&&i<=127569||131072<=i&&i<=194367||177984<=i&&i<=196605||196608<=i&&i<=262141?"W":32<=i&&i<=126||162<=i&&i<=163||165<=i&&i<=166||i==172||i==175||10214<=i&&i<=10221||10629<=i&&i<=10630?"Na":i==161||i==164||167<=i&&i<=168||i==170||173<=i&&i<=174||176<=i&&i<=180||182<=i&&i<=186||188<=i&&i<=191||i==198||i==208||215<=i&&i<=216||222<=i&&i<=225||i==230||232<=i&&i<=234||236<=i&&i<=237||i==240||242<=i&&i<=243||247<=i&&i<=250||i==252||i==254||i==257||i==273||i==275||i==283||294<=i&&i<=295||i==299||305<=i&&i<=307||i==312||319<=i&&i<=322||i==324||328<=i&&i<=331||i==333||338<=i&&i<=339||358<=i&&i<=359||i==363||i==462||i==464||i==466||i==468||i==470||i==472||i==474||i==476||i==593||i==609||i==708||i==711||713<=i&&i<=715||i==717||i==720||728<=i&&i<=731||i==733||i==735||768<=i&&i<=879||913<=i&&i<=929||931<=i&&i<=937||945<=i&&i<=961||963<=i&&i<=969||i==1025||1040<=i&&i<=1103||i==1105||i==8208||8211<=i&&i<=8214||8216<=i&&i<=8217||8220<=i&&i<=8221||8224<=i&&i<=8226||8228<=i&&i<=8231||i==8240||8242<=i&&i<=8243||i==8245||i==8251||i==8254||i==8308||i==8319||8321<=i&&i<=8324||i==8364||i==8451||i==8453||i==8457||i==8467||i==8470||8481<=i&&i<=8482||i==8486||i==8491||8531<=i&&i<=8532||8539<=i&&i<=8542||8544<=i&&i<=8555||8560<=i&&i<=8569||i==8585||8592<=i&&i<=8601||8632<=i&&i<=8633||i==8658||i==8660||i==8679||i==8704||8706<=i&&i<=8707||8711<=i&&i<=8712||i==8715||i==8719||i==8721||i==8725||i==8730||8733<=i&&i<=8736||i==8739||i==8741||8743<=i&&i<=8748||i==8750||8756<=i&&i<=8759||8764<=i&&i<=8765||i==8776||i==8780||i==8786||8800<=i&&i<=8801||8804<=i&&i<=8807||8810<=i&&i<=8811||8814<=i&&i<=8815||8834<=i&&i<=8835||8838<=i&&i<=8839||i==8853||i==8857||i==8869||i==8895||i==8978||9312<=i&&i<=9449||9451<=i&&i<=9547||9552<=i&&i<=9587||9600<=i&&i<=9615||9618<=i&&i<=9621||9632<=i&&i<=9633||9635<=i&&i<=9641||9650<=i&&i<=9651||9654<=i&&i<=9655||9660<=i&&i<=9661||9664<=i&&i<=9665||9670<=i&&i<=9672||i==9675||9678<=i&&i<=9681||9698<=i&&i<=9701||i==9711||9733<=i&&i<=9734||i==9737||9742<=i&&i<=9743||9748<=i&&i<=9749||i==9756||i==9758||i==9792||i==9794||9824<=i&&i<=9825||9827<=i&&i<=9829||9831<=i&&i<=9834||9836<=i&&i<=9837||i==9839||9886<=i&&i<=9887||9918<=i&&i<=9919||9924<=i&&i<=9933||9935<=i&&i<=9953||i==9955||9960<=i&&i<=9983||i==10045||i==10071||10102<=i&&i<=10111||11093<=i&&i<=11097||12872<=i&&i<=12879||57344<=i&&i<=63743||65024<=i&&i<=65039||i==65533||127232<=i&&i<=127242||127248<=i&&i<=127277||127280<=i&&i<=127337||127344<=i&&i<=127386||917760<=i&&i<=917999||983040<=i&&i<=1048573||1048576<=i&&i<=1114109?"A":"N"},n.characterLength=function(o){var e=this.eastAsianWidth(o);return e=="F"||e=="W"||e=="A"?2:1};function t(o){return o.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}n.length=function(o){for(var e=t(o),s=0,i=0;i<e.length;i++)s=s+this.characterLength(e[i]);return s},n.slice=function(o,e,s){textLen=n.length(o),e=e||0,s=s||1,e<0&&(e=textLen+e),s<0&&(s=textLen+s);for(var i="",a=0,f=t(o),d=0;d<f.length;d++){var c=f[d],u=n.length(c);if(a>=e-(u==2?1:0))if(a+u<=s)i+=c;else break;a+=u}return i}})(Ln);var ci=Ln.exports,mi=Pn(ci),ui=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g},pi=Pn(ui);function ur(r,n={}){if(typeof r!="string"||r.length===0||(n={ambiguousIsNarrow:!0,...n},r=Un(r),r.length===0))return 0;r=r.replace(pi()," ");let t=n.ambiguousIsNarrow?1:2,o=0;for(let e of r){let s=e.codePointAt(0);if(s<=31||s>=127&&s<=159||s>=768&&s<=879)continue;switch(mi.eastAsianWidth(e)){case"F":case"W":o+=2;break;case"A":o+=t;break;default:o+=1}}return o}var jr=10,Tn=(r=0)=>(n)=>`\x1B[${n+r}m`,Nn=(r=0)=>(n)=>`\x1B[${38+r};5;${n}m`,In=(r=0)=>(n,t,o)=>`\x1B[${38+r};2;${n};${t};${o}m`,$={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys($.modifier);var li=Object.keys($.color),yi=Object.keys($.bgColor);[...li];function hi(){let r=new Map;for(let[n,t]of Object.entries($)){for(let[o,e]of Object.entries(t))$[o]={open:`\x1B[${e[0]}m`,close:`\x1B[${e[1]}m`},t[o]=$[o],r.set(e[0],e[1]);Object.defineProperty($,n,{value:t,enumerable:!1})}return Object.defineProperty($,"codes",{value:r,enumerable:!1}),$.color.close="\x1B[39m",$.bgColor.close="\x1B[49m",$.color.ansi=Tn(),$.color.ansi256=Nn(),$.color.ansi16m=In(),$.bgColor.ansi=Tn(jr),$.bgColor.ansi256=Nn(jr),$.bgColor.ansi16m=In(jr),Object.defineProperties($,{rgbToAnsi256:{value:(n,t,o)=>n===t&&t===o?n<8?16:n>248?231:Math.round((n-8)/247*24)+232:16+36*Math.round(n/255*5)+6*Math.round(t/255*5)+Math.round(o/255*5),enumerable:!1},hexToRgb:{value:(n)=>{let t=/[a-f\d]{6}|[a-f\d]{3}/i.exec(n.toString(16));if(!t)return[0,0,0];let[o]=t;o.length===3&&(o=[...o].map((s)=>s+s).join(""));let e=Number.parseInt(o,16);return[e>>16&255,e>>8&255,e&255]},enumerable:!1},hexToAnsi256:{value:(n)=>$.rgbToAnsi256(...$.hexToRgb(n)),enumerable:!1},ansi256ToAnsi:{value:(n)=>{if(n<8)return 30+n;if(n<16)return 90+(n-8);let t,o,e;if(n>=232)t=((n-232)*10+8)/255,o=t,e=t;else{n-=16;let a=n%36;t=Math.floor(n/36)/5,o=Math.floor(a/6)/5,e=a%6/5}let s=Math.max(t,o,e)*2;if(s===0)return 30;let i=30+(Math.round(e)<<2|Math.round(o)<<1|Math.round(t));return s===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(n,t,o)=>$.ansi256ToAnsi($.rgbToAnsi256(n,t,o)),enumerable:!1},hexToAnsi:{value:(n)=>$.ansi256ToAnsi($.hexToAnsi256(n)),enumerable:!1}}),$}var Ri=hi(),_r=new Set(["\x1B","\x9B"]),gi=39,Zr="\x07",qn="[",wi="]",Bn="m",zr=`${wi}8;;`,An=(r)=>`${_r.values().next().value}${qn}${r}${Bn}`,Hn=(r)=>`${_r.values().next().value}${zr}${r}${Zr}`,bi=(r)=>r.split(" ").map((n)=>ur(n)),Vr=(r,n,t)=>{let o=[...n],e=!1,s=!1,i=ur(Un(r[r.length-1]));for(let[a,f]of o.entries()){let d=ur(f);if(i+d<=t?r[r.length-1]+=f:(r.push(f),i=0),_r.has(f)&&(e=!0,s=o.slice(a+1).join("").startsWith(zr)),e){s?f===Zr&&(e=!1,s=!1):f===Bn&&(e=!1);continue}i+=d,i===t&&a<o.length-1&&(r.push(""),i=0)}!i&&r[r.length-1].length>0&&r.length>1&&(r[r.length-2]+=r.pop())},Ei=(r)=>{let n=r.split(" "),t=n.length;for(;t>0&&!(ur(n[t-1])>0);)t--;return t===n.length?r:n.slice(0,t).join(" ")+n.slice(t).join("")},xi=(r,n,t={})=>{if(t.trim!==!1&&r.trim()==="")return"";let o="",e,s,i=bi(r),a=[""];for(let[d,c]of r.split(" ").entries()){t.trim!==!1&&(a[a.length-1]=a[a.length-1].trimStart());let u=ur(a[a.length-1]);if(d!==0&&(u>=n&&(t.wordWrap===!1||t.trim===!1)&&(a.push(""),u=0),(u>0||t.trim===!1)&&(a[a.length-1]+=" ",u++)),t.hard&&i[d]>n){let l=n-u,R=1+Math.floor((i[d]-l-1)/n);Math.floor((i[d]-1)/n)<R&&a.push(""),Vr(a,c,n);continue}if(u+i[d]>n&&u>0&&i[d]>0){if(t.wordWrap===!1&&u<n){Vr(a,c,n);continue}a.push("")}if(u+i[d]>n&&t.wordWrap===!1){Vr(a,c,n);continue}a[a.length-1]+=c}t.trim!==!1&&(a=a.map((d)=>Ei(d)));let f=[...a.join(`
|
|
13
|
+
`)];for(let[d,c]of f.entries()){if(o+=c,_r.has(c)){let{groups:l}=new RegExp(`(?:\\${qn}(?<code>\\d+)m|\\${zr}(?<uri>.*)${Zr})`).exec(f.slice(d).join(""))||{groups:{}};if(l.code!==void 0){let R=Number.parseFloat(l.code);e=R===gi?void 0:R}else l.uri!==void 0&&(s=l.uri.length===0?void 0:l.uri)}let u=Ri.codes.get(Number(e));f[d+1]===`
|
|
14
|
+
`?(s&&(o+=Hn("")),e&&u&&(o+=An(u))):c===`
|
|
15
|
+
`&&(e&&u&&(o+=An(e)),s&&(o+=Hn(s)))}return o};function Sn(r,n,t){return String(r).normalize().replace(/\r\n/g,`
|
|
6
16
|
`).split(`
|
|
7
|
-
`).map((
|
|
8
|
-
`)}var
|
|
9
|
-
`),
|
|
10
|
-
`),
|
|
11
|
-
`),
|
|
12
|
-
`).length-1;this.output.write(
|
|
13
|
-
`);this.output.write(
|
|
14
|
-
`).slice(
|
|
15
|
-
`)),this._prevFrame=
|
|
16
|
-
${
|
|
17
|
-
`,r
|
|
18
|
-
${
|
|
19
|
-
${
|
|
20
|
-
`;case"submit":return`${
|
|
21
|
-
${
|
|
22
|
-
${
|
|
23
|
-
`}}}).prompt();var
|
|
24
|
-
${
|
|
25
|
-
`,
|
|
26
|
-
${
|
|
27
|
-
${
|
|
28
|
-
`}}}).prompt()},
|
|
29
|
-
${
|
|
30
|
-
`;switch(this.state){case"submit":return`${
|
|
31
|
-
${
|
|
32
|
-
${
|
|
33
|
-
${
|
|
34
|
-
`}}}).prompt()};var
|
|
35
|
-
|
|
36
|
-
`)},
|
|
37
|
-
`)},
|
|
38
|
-
${
|
|
39
|
-
|
|
40
|
-
`)},
|
|
41
|
-
`);
|
|
17
|
+
`).map((o)=>xi(o,n,t)).join(`
|
|
18
|
+
`)}var $i=["up","down","left","right","space","enter","cancel"],$r={actions:new Set($i),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]])};function Jr(r,n){if(typeof r=="string")return $r.aliases.get(r)===n;for(let t of r)if(t!==void 0&&Jr(t,n))return!0;return!1}function _i(r,n){if(r===n)return;let t=r.split(`
|
|
19
|
+
`),o=n.split(`
|
|
20
|
+
`),e=[];for(let s=0;s<Math.max(t.length,o.length);s++)t[s]!==o[s]&&e.push(s);return e}var Oi=globalThis.process.platform.startsWith("win"),Kr=Symbol("clack:cancel");function A(r){return r===Kr}function xr(r,n){let t=r;t.isTTY&&t.setRawMode(n)}function jn({input:r=Wn,output:n=Mn,overwrite:t=!0,hideCursor:o=!0}={}){let e=V.createInterface({input:r,output:n,prompt:"",tabSize:1});V.emitKeypressEvents(r,e),r.isTTY&&r.setRawMode(!0);let s=(i,{name:a,sequence:f})=>{let d=String(i);if(Jr([d,a,f],"cancel")){o&&n.write(I.cursor.show),process.exit(0);return}if(!t)return;V.moveCursor(n,a==="return"?0:-1,a==="return"?-1:0,()=>{V.clearLine(n,1,()=>{r.once("keypress",s)})})};return o&&n.write(I.cursor.hide),r.once("keypress",s),()=>{r.off("keypress",s),o&&n.write(I.cursor.show),r.isTTY&&!Oi&&r.setRawMode(!1),e.terminal=!1,e.close()}}var ki=Object.defineProperty,vi=(r,n,t)=>(n in r)?ki(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,W=(r,n,t)=>(vi(r,typeof n!="symbol"?n+"":n,t),t);class Or{constructor(r,n=!0){W(this,"input"),W(this,"output"),W(this,"_abortSignal"),W(this,"rl"),W(this,"opts"),W(this,"_render"),W(this,"_track",!1),W(this,"_prevFrame",""),W(this,"_subscribers",new Map),W(this,"_cursor",0),W(this,"state","initial"),W(this,"error",""),W(this,"value");let{input:t=Wn,output:o=Mn,render:e,signal:s,...i}=r;this.opts=i,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=s,this.input=t,this.output=o}unsubscribe(){this._subscribers.clear()}setSubscriber(r,n){let t=this._subscribers.get(r)??[];t.push(n),this._subscribers.set(r,t)}on(r,n){this.setSubscriber(r,{cb:n})}once(r,n){this.setSubscriber(r,{cb:n,once:!0})}emit(r,...n){let t=this._subscribers.get(r)??[],o=[];for(let e of t)e.cb(...n),e.once&&o.push(()=>t.splice(t.indexOf(e),1));for(let e of o)e()}prompt(){return new Promise((r,n)=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),r(Kr);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}let t=new ai;t._write=(o,e,s)=>{this._track&&(this.value=this.rl?.line.replace(/\t/g,""),this._cursor=this.rl?.cursor??0,this.emit("value",this.value)),s()},this.input.pipe(t),this.rl=vn.createInterface({input:this.input,output:t,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),vn.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),this.opts.initialValue!==void 0&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),xr(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(I.cursor.show),this.output.off("resize",this.render),xr(this.input,!1),r(this.value)}),this.once("cancel",()=>{this.output.write(I.cursor.show),this.output.off("resize",this.render),xr(this.input,!1),r(Kr)})})}onKeypress(r,n){if(this.state==="error"&&(this.state="active"),n?.name&&(!this._track&&$r.aliases.has(n.name)&&this.emit("cursor",$r.aliases.get(n.name)),$r.actions.has(n.name)&&this.emit("cursor",n.name)),r&&(r.toLowerCase()==="y"||r.toLowerCase()==="n")&&this.emit("confirm",r.toLowerCase()==="y"),r==="\t"&&this.opts.placeholder&&(this.value||(this.rl?.write(this.opts.placeholder),this.emit("value",this.opts.placeholder))),r&&this.emit("key",r.toLowerCase()),n?.name==="return"){if(this.opts.validate){let t=this.opts.validate(this.value);t&&(this.error=t instanceof Error?t.message:t,this.state="error",this.rl?.write(this.value))}this.state!=="error"&&(this.state="submit")}Jr([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(`
|
|
21
|
+
`),xr(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let r=Sn(this._prevFrame,process.stdout.columns,{hard:!0}).split(`
|
|
22
|
+
`).length-1;this.output.write(I.cursor.move(-999,r*-1))}render(){let r=Sn(this._render(this)??"",process.stdout.columns,{hard:!0});if(r!==this._prevFrame){if(this.state==="initial")this.output.write(I.cursor.hide);else{let n=_i(this._prevFrame,r);if(this.restoreCursor(),n&&n?.length===1){let t=n[0];this.output.write(I.cursor.move(0,t)),this.output.write(I.erase.lines(1));let o=r.split(`
|
|
23
|
+
`);this.output.write(o[t]),this._prevFrame=r,this.output.write(I.cursor.move(0,o.length-t-1));return}if(n&&n?.length>1){let t=n[0];this.output.write(I.cursor.move(0,t)),this.output.write(I.erase.down());let o=r.split(`
|
|
24
|
+
`).slice(t);this.output.write(o.join(`
|
|
25
|
+
`)),this._prevFrame=r;return}this.output.write(I.erase.down())}this.output.write(r),this.state==="initial"&&(this.state="active"),this._prevFrame=r}}}class Yr extends Or{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(r){super(r,!1),this.value=!!r.initialValue,this.on("value",()=>{this.value=this._value}),this.on("confirm",(n)=>{this.output.write(I.cursor.move(0,-1)),this.value=n,this.state="submit",this.close()}),this.on("cursor",()=>{this.value=!this.value})}}var Ti;Ti=new WeakMap;var Ni=Object.defineProperty,Ii=(r,n,t)=>(n in r)?Ni(r,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[n]=t,Cn=(r,n,t)=>(Ii(r,typeof n!="symbol"?n+"":n,t),t);class Xr extends Or{constructor(r){super(r,!1),Cn(this,"options"),Cn(this,"cursor",0),this.options=r.options,this.cursor=this.options.findIndex(({value:n})=>n===r.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",(n)=>{switch(n){case"left":case"up":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;break}this.changeValue()})}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value}}class Qr extends Or{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return`${this.value}\u2588`;let r=this.value.slice(0,this.cursor),[n,...t]=this.value.slice(this.cursor);return`${r}${Gn.default.inverse(n)}${t.join("")}`}get cursor(){return this._cursor}constructor(r){super(r),this.on("finalize",()=>{this.value||(this.value=r.defaultValue)})}}var p=cr(Br(),1),kr=cr(Lr(),1);import P from"process";function Ai(){return P.platform!=="win32"?P.env.TERM!=="linux":!!P.env.CI||!!P.env.WT_SESSION||!!P.env.TERMINUS_SUBLIME||P.env.ConEmuTask==="{cmd::Cmder}"||P.env.TERM_PROGRAM==="Terminus-Sublime"||P.env.TERM_PROGRAM==="vscode"||P.env.TERM==="xterm-256color"||P.env.TERM==="alacritty"||P.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var Fr=Ai(),v=(r,n)=>Fr?r:n,Hi=v("\u25C6","*"),Vn=v("\u25A0","x"),Kn=v("\u25B2","x"),nn=v("\u25C7","o"),Si=v("\u250C","T"),_=v("\u2502","|"),or=v("\u2514","\u2014"),Dr=v("\u25CF",">"),rn=v("\u25CB"," "),Ke=v("\u25FB","[\u2022]"),Ze=v("\u25FC","[+]"),ze=v("\u25FB","[ ]"),Je=v("\u25AA","\u2022"),Ye=v("\u2500","-"),Xe=v("\u256E","+"),Qe=v("\u251C","+"),Fe=v("\u256F","+"),Ci=v("\u25CF","\u2022"),Wi=v("\u25C6","*"),Mi=v("\u25B2","!"),Gi=v("\u25A0","x"),tn=(r)=>{switch(r){case"initial":case"active":return p.default.cyan(Hi);case"cancel":return p.default.red(Vn);case"error":return p.default.yellow(Kn);case"submit":return p.default.green(nn)}},Ui=(r)=>{let{cursor:n,options:t,style:o}=r,e=r.maxItems??Number.POSITIVE_INFINITY,s=Math.max(process.stdout.rows-4,0),i=Math.min(s,Math.max(e,5)),a=0;n>=a+i-3?a=Math.max(Math.min(n-i+3,t.length-i),0):n<a+2&&(a=Math.max(n-2,0));let f=i<t.length&&a>0,d=i<t.length&&a+i<t.length;return t.slice(a,a+i).map((c,u,l)=>{let R=u===0&&f,h=u===l.length-1&&d;return R||h?p.default.dim("..."):o(c,u+a===n)})},T=(r)=>new Qr({validate:r.validate,placeholder:r.placeholder,defaultValue:r.defaultValue,initialValue:r.initialValue,render(){let n=`${p.default.gray(_)}
|
|
26
|
+
${tn(this.state)} ${r.message}
|
|
27
|
+
`,t=r.placeholder?p.default.inverse(r.placeholder[0])+p.default.dim(r.placeholder.slice(1)):p.default.inverse(p.default.hidden("_")),o=this.value?this.valueWithCursor:t;switch(this.state){case"error":return`${n.trim()}
|
|
28
|
+
${p.default.yellow(_)} ${o}
|
|
29
|
+
${p.default.yellow(or)} ${p.default.yellow(this.error)}
|
|
30
|
+
`;case"submit":return`${n}${p.default.gray(_)} ${p.default.dim(this.value||r.placeholder)}`;case"cancel":return`${n}${p.default.gray(_)} ${p.default.strikethrough(p.default.dim(this.value??""))}${this.value?.trim()?`
|
|
31
|
+
${p.default.gray(_)}`:""}`;default:return`${n}${p.default.cyan(_)} ${o}
|
|
32
|
+
${p.default.cyan(or)}
|
|
33
|
+
`}}}).prompt();var H=(r)=>{let n=r.active??"Yes",t=r.inactive??"No";return new Yr({active:n,inactive:t,initialValue:r.initialValue??!0,render(){let o=`${p.default.gray(_)}
|
|
34
|
+
${tn(this.state)} ${r.message}
|
|
35
|
+
`,e=this.value?n:t;switch(this.state){case"submit":return`${o}${p.default.gray(_)} ${p.default.dim(e)}`;case"cancel":return`${o}${p.default.gray(_)} ${p.default.strikethrough(p.default.dim(e))}
|
|
36
|
+
${p.default.gray(_)}`;default:return`${o}${p.default.cyan(_)} ${this.value?`${p.default.green(Dr)} ${n}`:`${p.default.dim(rn)} ${p.default.dim(n)}`} ${p.default.dim("/")} ${this.value?`${p.default.dim(rn)} ${p.default.dim(t)}`:`${p.default.green(Dr)} ${t}`}
|
|
37
|
+
${p.default.cyan(or)}
|
|
38
|
+
`}}}).prompt()},X=(r)=>{let n=(t,o)=>{let e=t.label??String(t.value);switch(o){case"selected":return`${p.default.dim(e)}`;case"active":return`${p.default.green(Dr)} ${e} ${t.hint?p.default.dim(`(${t.hint})`):""}`;case"cancelled":return`${p.default.strikethrough(p.default.dim(e))}`;default:return`${p.default.dim(rn)} ${p.default.dim(e)}`}};return new Xr({options:r.options,initialValue:r.initialValue,render(){let t=`${p.default.gray(_)}
|
|
39
|
+
${tn(this.state)} ${r.message}
|
|
40
|
+
`;switch(this.state){case"submit":return`${t}${p.default.gray(_)} ${n(this.options[this.cursor],"selected")}`;case"cancel":return`${t}${p.default.gray(_)} ${n(this.options[this.cursor],"cancelled")}
|
|
41
|
+
${p.default.gray(_)}`;default:return`${t}${p.default.cyan(_)} ${Ui({cursor:this.cursor,options:this.options,maxItems:r.maxItems,style:(o,e)=>n(o,e?"active":"inactive")}).join(`
|
|
42
|
+
${p.default.cyan(_)} `)}
|
|
43
|
+
${p.default.cyan(or)}
|
|
44
|
+
`}}}).prompt()};var on=(r="")=>{process.stdout.write(`${p.default.gray(or)} ${p.default.red(r)}
|
|
45
|
+
|
|
46
|
+
`)},Zn=(r="")=>{process.stdout.write(`${p.default.gray(Si)} ${r}
|
|
47
|
+
`)},zn=(r="")=>{process.stdout.write(`${p.default.gray(_)}
|
|
48
|
+
${p.default.gray(or)} ${r}
|
|
49
|
+
|
|
50
|
+
`)},m={message:(r="",{symbol:n=p.default.gray(_)}={})=>{let t=[`${p.default.gray(_)}`];if(r){let[o,...e]=r.split(`
|
|
51
|
+
`);t.push(`${n} ${o}`,...e.map((s)=>`${p.default.gray(_)} ${s}`))}process.stdout.write(`${t.join(`
|
|
42
52
|
`)}
|
|
43
|
-
`)},info:(
|
|
44
|
-
`);let
|
|
45
|
-
`);process.stdout.write(
|
|
46
|
-
`);let
|
|
47
|
-
`):process.stdout.write(`${
|
|
48
|
-
`),g(),i()};return{start:y,stop:B,message:(E="")=>{f=L(E??f)}}},It=async(n,o)=>{let r={},e=Object.keys(n);for(let i of e){let s=n[i],t=await s({results:r})?.catch((f)=>{throw f});if(typeof o?.onCancel=="function"&&U(t)){r[i]="canceled",o.onCancel({results:r});continue}r[i]=t}return r};var dr=!process.env.NO_COLOR&&(process.env.FORCE_COLOR||process.stdout.isTTY),gr=["blue","cyan","gray","green","magenta","red","white","yellow"],hr=["bold","dim","italic","underline","reset"],zt={bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",reset:"\x1B[0m",underline:"\x1B[4m"},br={"\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 st(n){return(o)=>dr?`${n}${o}${zt.reset}`:o}function Kt({bright:n=!1,color:o}){let r=Bun.color(o,"ansi");if(!r)return"";return n?br[r]||r:r}var yr=gr.reduce((n,o)=>{return n[o]=st(Kt({color:o})),n[`${o}Bright`]=st(Kt({bright:!0,color:o})),n},{}),wr=hr.reduce((n,o)=>{return n[o]=st(zt[o]),n},{}),w={...yr,...wr};var x=({prefix:n="",level:o=process.env.DEBUG?0:1}={})=>{function r(...f){if(o<=0){let a=f.join(" ");console.log(An({level:w.dim("DEBUG"),message:a,prefix:n}))}}function e(...f){if(o<=1){let a=f.join(" ");console.info(An({level:w.cyan("INFO "),message:a,prefix:n}))}}function i(...f){if(o<=2){let a=f.join(" ");console.warn(An({level:w.yellow("WARN "),message:a,prefix:n}))}}function s(...f){if(o<=3){let a=f.join(" ");console.error(An({level:w.red("ERROR"),message:a,prefix:n}))}}function t(f){return x({level:o,prefix:`${n}:${f}`})}return{child:t,debug:r,error:s,info:e,warn:i}},ft=x();function An({prefix:n,level:o,message:r}){let e=new Date().toISOString().split("T")[1]?.split(".")[0]||"",i=n?`[${n}] `:"";return`${w.dim(e||"")} ${o} ${i}${r}`}var p={arrow:w.yellow,bold:w.bold,boolean:w.cyan,bullet:w.yellow,busy:w.yellow,command:w.green,dim:w.dim,error:w.red,flag:w.yellow,info:w.cyan,number:w.magenta,offline:w.red,online:w.green,separator:w.dim,string:w.green,success:w.green,value:w.cyan,warning:w.yellow};var Ai=x({prefix:"cli-core"}).child("error");var j=new Uint32Array(65536),xr=(n,o)=>{let r=n.length,e=o.length,i=1<<r-1,s=-1,t=0,f=r,a=r;while(a--)j[n.charCodeAt(a)]|=1<<a;for(a=0;a<e;a++){let c=j[o.charCodeAt(a)],m=c|t;if(c|=(c&s)+s^s,t|=~(c|s),s&=c,t&i)f++;if(s&i)f--;t=t<<1|1,s=s<<1|~(m|t),t&=m}a=r;while(a--)j[n.charCodeAt(a)]=0;return f},$r=(n,o)=>{let r=o.length,e=n.length,i=[],s=[],t=Math.ceil(r/32),f=Math.ceil(e/32);for(let g=0;g<t;g++)s[g]=-1,i[g]=0;let a=0;for(;a<f-1;a++){let g=0,$=-1,L=a*32,_=Math.min(32,e)+L;for(let y=L;y<_;y++)j[n.charCodeAt(y)]|=1<<y;for(let y=0;y<r;y++){let B=j[o.charCodeAt(y)],E=s[y/32|0]>>>y&1,R=i[y/32|0]>>>y&1,v=B|g,Y=((B|R)&$)+$^$|B|R,D=g|~(Y|$),xn=$&Y;if(D>>>31^E)s[y/32|0]^=1<<y;if(xn>>>31^R)i[y/32|0]^=1<<y;D=D<<1|E,xn=xn<<1|R,$=xn|~(v|D),g=D&v}for(let y=L;y<_;y++)j[n.charCodeAt(y)]=0}let c=0,m=-1,l=a*32,u=Math.min(32,e-l)+l;for(let g=l;g<u;g++)j[n.charCodeAt(g)]|=1<<g;let b=e;for(let g=0;g<r;g++){let $=j[o.charCodeAt(g)],L=s[g/32|0]>>>g&1,_=i[g/32|0]>>>g&1,y=$|c,B=(($|_)&m)+m^m|$|_,E=c|~(B|m),R=m&B;if(b+=E>>>e-1&1,b-=R>>>e-1&1,E>>>31^L)s[g/32|0]^=1<<g;if(R>>>31^_)i[g/32|0]^=1<<g;E=E<<1|L,R=R<<1|_,m=R|~(y|E),c=E&y}for(let g=l;g<u;g++)j[n.charCodeAt(g)]=0;return b},kt=(n,o)=>{if(n.length<o.length){let r=o;o=n,n=r}if(o.length===0)return n.length;if(n.length<=32)return xr(n,o);return $r(n,o)};function Jt(n,o,r=3){return o.map((s)=>({distance:kt(n.toLowerCase(),s.toLowerCase()),option:s})).filter(({distance:s})=>s<=Math.max(3,n.length/2)).sort((s,t)=>s.distance-t.distance).slice(0,r).map(({option:s})=>s)}function Yt(n,o){return o[n.toLowerCase()]||null}var jt=x({prefix:"cli-core"}).child("graceful");async function an(n,o={}){let{fallback:r,logLevel:e="warn",message:i="Operation failed gracefully"}=o;try{return await n()}catch(s){let t=s instanceof Error?s.message:String(s);if(jt[e](`${i}: ${t}`),r)try{await r()}catch(f){jt.error(`Fallback also failed: ${f instanceof Error?f.message:String(f)}`)}return}}var Er={backoffMultiplier:2,initialDelay:1000,maxAttempts:3,maxDelay:30000,onRetry:(n,o)=>{ft.warn(`Retry attempt ${n}: ${o.message}`)},retryableErrors:["ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENOTFOUND","rate limit","429","503","502","504","npm ERR!","EPUBLISHCONFLICT"]};async function Z(n,o={}){let r={...Er,...o},e=new Error("Operation failed");for(let i=1;i<=r.maxAttempts;i++)try{return await n()}catch(s){if(e=s instanceof Error?s:new Error(String(s)),!r.retryableErrors.some((a)=>e.message.toLowerCase().includes(a.toLowerCase()))||i===r.maxAttempts)throw e;r.onRetry(i,e);let f=Math.min(r.initialDelay*r.backoffMultiplier**(i-1),r.maxDelay);await new Promise((a)=>setTimeout(a,f))}throw e}var k=(n)=>{return n.map=(o)=>k((r)=>o(n(r))),n.or=(o)=>k((r)=>{try{return n(r)}catch(e){return o(r)}}),n},Xn=()=>"bad banditype"();var Zt=(n)=>k((o)=>n.includes(o)?o:Xn()),_n=(n)=>k((o)=>typeof o===typeof n?o:Xn()),gn=()=>_n(""),Qt=()=>_n(0),Vt=()=>_n(!0);var Ft=()=>_n();var Dt=(n)=>k((o)=>o instanceof n?o:Xn()),at=(n)=>Dt(Object).map((o)=>{let r={};for(let e in o){let i=n(o[e]);i!==void 0&&(r[e]=i)}return r}),cn=(n)=>Dt(Object).map((o)=>{let r={};for(let e in n){let i=n[e](o[e]);i!==void 0&&(r[e]=i)}return r});function Or(n,o){return k((r)=>{try{return n(r)}catch{try{return o(r)}catch{throw new Error("No matching schema in union")}}})}function nn(n,o){return(r)=>{if(r===void 0)return o;return n(r)}}function no(){return k((n)=>{let o=Qt()(n);if(!Number.isInteger(o)||o<=0)throw new Error("Must be a positive integer");return o})}function to(){return k((n)=>{let o=gn()(n);try{return new URL(o),o}catch{throw new Error("Must be a valid URL")}})}function oo(n,o){return k((r)=>{let e=gn()(r);if(!n.test(e))throw new Error(o||`Must match pattern ${n}`);return e})}function hn(n){return{parse(o){try{return n(o)}catch(r){throw new Error(r instanceof Error?r.message:"Validation failed")}},safeParse(o){try{return{data:n(o),success:!0}}catch(r){return{error:r instanceof Error?r:new Error("Validation failed"),success:!1}}},validator:n}}function tn(){return Or(Ft(),gn())}function on(n){return nn(gn(),n)}function mn(n){return nn(Vt(),n)}function Un(n,o){return nn(Zt(n),o)}import{existsSync as V}from"fs";import{copyFile as Ar,mkdir as ln,readdir as mt}from"fs/promises";import{join as T,resolve as Xr}from"path";import{parseArgs as _r}from"util";var{$:pn}=globalThis.Bun;import{join as so}from"path";var{$:io}=globalThis.Bun;import{tmpdir as Rr}from"os";var ro={MACHINES_DIR:"machines",TEMP_DIR:Rr()};var Sr=cn({directory:on("./gh-runners"),labels:tn(),name:on("runner"),numberOfMachines:nn(no(),1),os:Un(["osx","linux","windows"],"osx"),overwrite:mn(!1),run:mn(!1),runnerGroup:tn(),url:tn()}),Tr=hn(Sr),eo=hn(cn({defaultProfile:tn(),profiles:at(Tr.validator)}));var Lr=["hydra.json",".hydra.json","hydra.toml",".hydra.toml"];async function Nr(n=process.cwd()){for(let o of Lr){let r=so(n,o);if(await Bun.file(r).exists())return r}return null}async function A(n){let o=n?.configPath||await Nr();if(!o)return null;let r=Bun.file(o);if(!await r.exists())return null;try{let e=await r.text(),i=o.endsWith(".toml")?await Gr(e):JSON.parse(e);return eo.parse(i)}catch(e){if(e instanceof Error)throw new Error(`Invalid config file: ${e.message}`);throw e}}async function X(n,o){if(!n)return null;let r=o||n.defaultProfile;if(!r)return null;return n.profiles[r]||null}async function Gr(n){let o=so(ro.TEMP_DIR,`hydra-config-${Date.now()}.toml`);await Bun.write(o,n);try{let r=await import(o);return await io`rm -f ${o}`.quiet(),r.default}catch(r){throw await io`rm -f ${o}`.quiet(),new Error(`Failed to parse TOML configuration: ${r}`)}}var Ur=x({prefix:"hydra"}).child("backup");async function qr(){let{values:n}=_r({allowPositionals:!0,args:Bun.argv,options:{compress:{default:!0,type:"boolean"},config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},list:{default:!1,short:"l",type:"boolean"},output:{short:"o",type:"string"},profile:{short:"p",type:"string"},restore:{short:"r",type:"string"}},strict:!0}),o=await A({configPath:n.config}),r=await X(o,n.profile);return{compress:n.compress,directory:n.directory||r?.directory||`${process.cwd()}/gh-runners`,list:n.list,output:n.output,restore:n.restore}}async function fo(){try{let n=await qr();if(n.list){await vr(n.output||T(n.directory,"backups"));return}if(n.restore){await Hr(n);return}await Cr(n)}catch(n){Ur.error("Backup operation failed:",n),process.exit(1)}}async function Cr(n){let o=Xr(n.directory),r=T(o,"machines");if(!V(r)){h.error(`No runners found in ${n.directory}`);return}let e=W();e.start("Creating backup...");try{let i=await mt(r);if(i.length===0){e.stop("No runners to backup");return}let s=`backup-${new Date().toISOString().replace(/[:.]/g,"-")}`,t=n.output||T(o,"backups"),f=T(t,s);await ln(f,{recursive:!0});let a=0,c=[];for(let l of i){let u=T(r,l),b=T(f,"runners",l);await ln(b,{recursive:!0});let g=[".runner",".credentials",".credentials_rsaparams",".path",".env","config.sh"];for(let $ of g){let L=T(u,$);if(V(L)){let _=T(b,$);await Ar(L,_);let y=await Bun.file(L).stat();a+=y.size,c.push(`runners/${l}/${$}`)}}}let m={configFiles:c,date:new Date,id:s,runnerCount:i.length,size:a};if(await Bun.write(T(f,"metadata.json"),JSON.stringify(m,null,2)),n.compress){e.message("Compressing backup..."),await pn`cd ${t} && tar -czf ${s}.tar.gz ${s}`.quiet(),await pn`rm -rf ${f}`.quiet();let l=await Bun.file(T(t,`${s}.tar.gz`)).stat();e.stop(`Backup created: ${s}.tar.gz (${ct(l.size)})`)}else e.stop(`Backup created: ${s} (${ct(a)})`);h.success(`Backed up ${i.length} runner(s)`)}catch(i){throw e.stop("Backup failed"),i}}async function vr(n){if(!V(n)){h.info("No backups found");return}let o=W();o.start("Scanning backups...");try{let r=await mt(n),e=[];for(let i of r){let s=T(n,i);if(i.endsWith(".tar.gz")){let t=i.replace(".tar.gz",""),f=await Bun.file(s).stat();e.push({configFiles:[],date:new Date(f.mtime),id:t,runnerCount:0,size:f.size})}else{let t=T(s,"metadata.json");if(V(t)){let f=await Bun.file(t).json();e.push(f)}}}if(o.stop("Found backups"),e.length===0){h.info("No backups found");return}console.log(),console.log(p.bold("\uD83D\uDCE6 Available Backups")),console.log("\u2500".repeat(80));for(let i of e.sort((s,t)=>new Date(t.date).getTime()-new Date(s.date).getTime())){let s=new Date(i.date).toLocaleString(),t=ct(i.size),f=i.runnerCount>0?`${i.runnerCount} runners`:"compressed";console.log(`${p.value(i.id)}`),console.log(` Date: ${s}`),console.log(` Size: ${t}`),console.log(` Content: ${f}`),console.log()}}catch(r){throw o.stop("Failed to list backups"),r}}async function Hr(n){let o=n.output||T(n.directory,"backups"),r=T(o,n.restore),e=`${r}.tar.gz`,i=V(e),s=V(r);if(!i&&!s){h.error(`Backup not found: ${n.restore}`);return}if(!await C({initialValue:!1,message:"This will overwrite existing runner configurations. Continue?"})){h.info("Restore cancelled");return}let f=W();f.start("Restoring backup...");try{let a=r;if(i){f.message("Extracting backup...");let g=T(o,`temp-${Date.now()}`);await ln(g,{recursive:!0}),await pn`cd ${g} && tar -xzf ${e}`.quiet(),a=T(g,n.restore)}let c=T(a,"metadata.json");if(!V(c))throw new Error("Invalid backup: metadata.json not found");await Bun.file(c).json();let m=T(a,"runners"),l=T(n.directory,"machines");await ln(l,{recursive:!0});let u=await mt(m),b=0;for(let g of u){let $=T(m,g),L=T(l,g);if(V(L)){let _=await Gn({message:`Runner ${g} already exists. What should we do?`,options:[{label:"Skip",value:"skip"},{label:"Overwrite",value:"overwrite"},{label:"Rename",value:"rename"}]});if(_==="skip")continue;else if(_==="rename"){let y=await q({message:"Enter new runner name:",placeholder:`${g}-restored`});if(!y)continue;let B=T(l,y);await ln(B,{recursive:!0}),await pn`cp -r ${$}/* ${B}/`.quiet(),b++;continue}}await ln(L,{recursive:!0}),await pn`cp -r ${$}/* ${L}/`.quiet(),b++}if(i){let g=a.replace(`/${n.restore}`,"");await pn`rm -rf ${g}`.quiet()}f.stop("Restore completed"),h.success(`Restored ${b} runner(s) from backup ${n.restore}`)}catch(a){throw f.stop("Restore failed"),a}}function ct(n){if(n<1024)return`${n}B`;if(n<1048576)return`${(n/1024).toFixed(1)}KB`;if(n<1073741824)return`${(n/1048576).toFixed(1)}MB`;return`${(n/1073741824).toFixed(2)}GB`}import{parseArgs as Kr}from"util";var{$:I}=globalThis.Bun;function bn(){let n=import.meta.path,o=n.substring(0,n.lastIndexOf("/"));return o.substring(0,o.lastIndexOf("/"))}var Pr=cn({directory:on(`${process.cwd()}/gh-runners`),labels:tn(),name:on("runner"),numberOfMachines:nn(oo(/^\d+$/,"Number of machines must be a positive integer"),"1"),os:Un(["osx","linux","windows"],"osx"),overwrite:mn(!1),run:mn(!1),token:on(process.env.GITHUB_PERSONAL_ACCESS_TOKEN??""),url:to()}),Os=hn(Pr);var rn=x({prefix:"WorkerManager"}),P=new Set,ao=!1;function Mr(){if(ao)return;ao=!0;let n=()=>{if(P.size>0)rn.info("Cleaning up workers...");co()};process.on("exit",n),process.on("SIGINT",n),process.on("SIGTERM",n),process.on("uncaughtException",(o)=>{rn.error("Uncaught exception:",o),n(),process.exit(1)})}function Br(n){P.add(n),rn.debug(`Worker added. Total workers: ${P.size}`),n.addEventListener("exit",()=>{P.delete(n),rn.debug(`Worker exited. Remaining workers: ${P.size}`)})}function Wr(n){if(P.has(n))n.terminate(),P.delete(n),rn.debug(`Worker removed. Remaining workers: ${P.size}`)}function co(){if(P.size>0){rn.info(`Terminating ${P.size} workers...`);for(let n of P)try{n.terminate()}catch(o){rn.error("Failed to terminate worker:",o)}P.clear()}}function Ir(){return P.size}Mr();var qn={add:Br,remove:Wr,get size(){return Ir()},terminateAll:co};var M=x({prefix:"createMachines"});async function Cn(){let n=await kr(),{overwrite:o,directory:r,numberOfMachines:e,os:i,run:s,name:t,labels:f,runnerGroup:a}=n,{token:c,url:m}=n;if(!m)throw new Error("URL (-u) parameter is required");if(!c){let b=zr(m),g=await C({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
49
|
-
${b}`});if(U(g)||!g)throw new Error("Token is required to create runners");M.info("Opening GitHub runner settings..."),await I`open ${b}`.quiet();let $=await q({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(L)=>{if(!L||L.trim().length===0)return"Token is required";return}});if(U($))throw new Error("Token is required to create runners");c=$.trim()}if(M.info(`Creating ${e} runners in ${r}`),M.debug(`OS: ${i}, Name: ${t}, Labels: ${f||"none"}`),await Bun.file(r).exists())if(o)M.warn(`Directory ${r} exists, removing...`),await I`rm -rf ${r}`;else throw new Error(`Directory ${r} already exists`);let u=await Jr({directory:r,os:i});if(await Yr({directory:r,numberOfMachines:e,overwrite:o,runnerBase:u}),!s){M.info("Runners created but not started");return}jr({directory:r,labels:f,name:t,numberOfMachines:e,runnerGroup:a,token:c,url:m})}function zr(n){try{let o=new URL(n),r=o.pathname.split("/").filter(Boolean);if(o.hostname==="github.com"||o.hostname==="www.github.com"){if(r[0]==="orgs"&&r[1])return`https://github.com/organizations/${r[1]}/settings/actions/runners/new`;else if(r.length>=2)return`https://github.com/${r[0]}/${r[1]}/settings/actions/runners/new`}else if(r[0]==="orgs"&&r[1])return`${o.origin}/organizations/${r[1]}/settings/actions/runners/new`;else if(r.length>=2)return`${o.origin}/${r[0]}/${r[1]}/settings/actions/runners/new`;return n}catch{return n}}async function kr(){let{values:n}=Kr({allowPositionals:!0,args:Bun.argv,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"},token:{short:"t",type:"string"},url:{short:"u",type:"string"}},strict:!0}),o=await A({configPath:n.config}),r=await X(o,n.profile),e={directory:n.directory,labels:n.labels,name:n.name,numberOfMachines:n.numberOfMachines,os:n.os,overwrite:n.overwrite,run:n.run,runnerGroup:n.runnerGroup,token:n.token,url:n.url};if(r)return{directory:e.directory??r.directory??`${process.cwd()}/gh-runners`,labels:e.labels??r.labels,name:e.name??r.name??"runner",numberOfMachines:e.numberOfMachines??String(r.numberOfMachines)??"1",os:e.os??r.os??"osx",overwrite:e.overwrite??r.overwrite??!1,run:e.run??r.run??!1,runnerGroup:e.runnerGroup??r.runnerGroup,token:e.token,url:e.url??r.url};return{directory:e.directory,labels:e.labels,name:e.name,numberOfMachines:e.numberOfMachines,os:e.os,overwrite:e.overwrite,run:e.run,runnerGroup:e.runnerGroup,token:e.token,url:e.url}}async function Jr({directory:n,os:o}){let r=M.child("download");r.info(`Fetching latest runner version for ${o}...`);let e=await Z(async()=>(await I`curl -Ls -o /dev/null -w "%{url_effective}" https://github.com/actions/runner/releases/latest`).text(),{onRetry:(c,m)=>{r.warn(`Retrying GitHub API call (attempt ${c}): ${m.message}`)}}),s=(await I`basename ${e}`).text().trim().replace("v",""),t=`actions-runner-${o}-x64-${s}.tar.gz`,f=`https://github.com/actions/runner/releases/download/v${s}/${t}`;if(r.debug(`Runner version: ${s}`),r.debug(`Download URL: ${f}`),await I`mkdir -p ${n}`,await I`mkdir -p ${n}/machines`,!await Bun.file(`${n}/${t}`).exists())r.info("Downloading runner image..."),await Z(async()=>await I`curl -o ${n}/${t} -L ${f}`,{maxAttempts:5,onRetry:(c,m)=>{r.warn(`Retrying runner download (attempt ${c}): ${m.message}`)}}),r.info("Download complete");else r.info("Runner image already exists, skipping download");return t}async function Yr({overwrite:n,numberOfMachines:o,directory:r,runnerBase:e}){let i=M.child("extract"),s=Number(o),t=(()=>{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}}})(),f=Math.min(Math.max(2,Math.floor(t/2)),s,8);i.info(`Extracting ${s} runners with concurrency of ${f}`);let a=Array.from({length:s},(m,l)=>l+1).map((m)=>({execute:async()=>{let l=`${r}/machines/${m}`;if(await Bun.file(l).exists())if(n)i.debug(`Machine ${m} already exists, removing...`),await I`rm -rf ${l}`;else{i.debug(`Machine ${m} already exists, skipping...`);return}await I`mkdir -p ${l}`,await I`tar xzf ${e} -C ${l.replace(`${r}/`,"")}`.cwd(r);let b=`${bn()}/src/runner`;await I`cp -R ${b}/hooks ${l}`,await I`cp -R ${b}/.runner-env ${l}/.runner-env`,i.debug(`Machine ${m} extracted successfully`)},runnerIndex:m})),c=[];for(let m=0;m<a.length;m+=f){let l=a.slice(m,m+f),u=await Promise.allSettled(l.map((b)=>b.execute()));for(let[b,g]of u.entries())if(g.status==="rejected")throw i.error(`Failed to extract runner ${l[b]?.runnerIndex}: ${g.reason}`),g.reason;c.push(...u)}i.info(`Successfully extracted ${s} runners`)}function jr({directory:n,numberOfMachines:o,token:r,url:e,name:i,labels:s,runnerGroup:t}){M.info(`Starting ${o} runners...`);for(let f=1;f<=Number(o);f++){let a=`${bn()}/src/runner-worker.ts`,c=`${i}-${f}`,m=new Worker(a,{name:c,ref:!0});m.addEventListener("open",()=>{M.info(`Worker ${c} started`),m.postMessage({index:f,labels:s,machineCwd:`${n}/machines/${f}`,name:i,runnerGroup:t,token:r,url:e})}),m.addEventListener("message",({data:l})=>{let u=l.type==="error"?"error":"info";M[u](`${c}: ${l.message}`)}),m.addEventListener("error",(l)=>{M.error(`Worker ${c} error:`,l)}),m.addEventListener("exit",(l)=>{M.info(`Worker ${c} exited with code ${l}`)}),qn.add(m)}M.info("All workers started. Press Ctrl+C to stop all machines")}import{existsSync as yn}from"fs";import{readdir as mo}from"fs/promises";import{join as F,resolve as Zr}from"path";import{parseArgs as Qr}from"util";var{$:lt}=globalThis.Bun;var Vr=x({prefix:"hydra"}).child("health");async function Fr(){let{values:n}=Qr({allowPositionals:!0,args:Bun.argv,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 A({configPath:n.config}),r=await X(o,n.profile);return{directory:n.directory||r?.directory||`${process.cwd()}/gh-runners`,fix:n.fix,json:n.json,runner:n.runner,token:n.token,url:n.url||r?.url}}async function lo(){try{let n=await Fr(),o=Zr(n.directory),r=F(o,"machines");if(!yn(r)){h.error(`No runners found in ${n.directory}`);return}let e=W();e.start("Performing health checks...");let i=await mo(r),s=[];for(let t of i){if(n.runner&&t!==n.runner)continue;let f=F(r,t),a=await Dr(t,f,n);s.push(a)}if(e.stop("Health checks completed"),n.json){console.log(JSON.stringify(s,null,2));return}if(re(s),n.fix)await ee(s,n)}catch(n){Vr.error("Failed to perform health checks:",n),process.exit(1)}}async function Dr(n,o,r){let e=[],i={configuration:!1,connectivity:!1,disk:{percentage:0,total:0,used:0},lastActivity:null,process:!1};try{let t=F(o,".runner");if(yn(t)){let f=await Bun.file(t).text(),a=await ne(f.trim());if(i.process=a,!a)e.push("Runner process is not running")}else e.push("No PID file found")}catch{e.push("Could not check process status")}try{let t=await te(o);if(i.disk=t,t.percentage>90)e.push(`Low disk space: ${t.percentage.toFixed(1)}% used`)}catch{e.push("Could not check disk space")}try{let t=F(o,"_diag");if(yn(t)){let f=await mo(t),a=null;for(let c of f)if(c.endsWith(".log")){let m=await Bun.file(F(t,c)).stat();if(!a||m.mtime>a)a=new Date(m.mtime)}if(i.lastActivity=a,a){let c=(Date.now()-a.getTime())/3600000;if(c>24)e.push(`No activity for ${Math.floor(c)} hours`)}}}catch{e.push("Could not check last activity")}try{let t=F(o,".runner"),f=F(o,".credentials");if(i.configuration=yn(t)&&yn(f),!i.configuration)e.push("Missing configuration files")}catch{e.push("Could not check configuration")}if(r.token&&r.url)try{let t=await oe(r.url,r.token);if(i.connectivity=t,!t)e.push("Cannot connect to GitHub API")}catch{e.push("Failed to check GitHub connectivity")}let s="healthy";if(e.length===0)s="healthy";else if(e.some((t)=>t.includes("not running")||t.includes("Missing configuration")||t.includes("Cannot connect")))s="critical";else if(e.length>0)s="warning";return{checks:i,issues:e,runner:n,status:s}}async function ne(n){try{return await lt`kill -0 ${n}`.quiet(),!0}catch{return!1}}async function te(n){let r=(await lt`df -k ${n} | tail -1`.text()).trim().split(/\s+/),e=parseInt(r[1]||"0",10)*1024,i=parseInt(r[2]||"0",10)*1024;return{percentage:parseInt(r[4]?.replace("%","")||"0",10),total:e,used:i}}async function oe(n,o){return Z(async()=>{let r=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!r)return!1;let[,e,i]=r,s=i?`https://api.github.com/repos/${e}/${i}`:`https://api.github.com/orgs/${e}`;return(await fetch(s,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${o}`}})).ok},{maxAttempts:3})}function re(n){console.log(),console.log(p.bold("\uD83C\uDFE5 Runner Health Status")),console.log("\u2500".repeat(80));let o={critical:"\u274C",healthy:"\u2705",unknown:"\u2753",warning:"\u26A0\uFE0F"},r={critical:p.error,healthy:p.success,unknown:p.dim,warning:p.warning};for(let i of n){let s=o[i.status],t=r[i.status];if(console.log(`${s} ${p.bold(`Runner ${i.runner}`)}: ${t(i.status.toUpperCase())}`),console.log(` Process: ${i.checks.process?"\u2705 Running":"\u274C Not running"}`),console.log(` Config: ${i.checks.configuration?"\u2705 Valid":"\u274C Missing"}`),i.checks.disk.total>0){let f=i.checks.disk.percentage>90?p.error:p.success;console.log(` Disk: ${f(`${i.checks.disk.percentage.toFixed(1)}% used`)}`)}if(i.checks.lastActivity){let a=(Date.now()-i.checks.lastActivity.getTime())/3600000>24?p.warning:p.success;console.log(` Last Activity: ${a(ie(i.checks.lastActivity))}`)}if(i.checks.connectivity!==null)console.log(` GitHub API: ${i.checks.connectivity?"\u2705 Connected":"\u274C Disconnected"}`);if(i.issues.length>0){console.log(" Issues:");for(let f of i.issues)console.log(` - ${p.dim(f)}`)}console.log()}let e={critical:n.filter((i)=>i.status==="critical").length,healthy:n.filter((i)=>i.status==="healthy").length,total:n.length,warning:n.filter((i)=>i.status==="warning").length};console.log("\u2500".repeat(80)),console.log(`Summary: Total: ${e.total} | ${p.success(`Healthy: ${e.healthy}`)} | ${p.warning(`Warning: ${e.warning}`)} | ${p.error(`Critical: ${e.critical}`)}`)}async function ee(n,o){let r=n.filter((i)=>i.status==="critical");if(r.length===0){h.info("No critical issues found that require fixing");return}if(console.log(),!await C({initialValue:!1,message:`Found ${r.length} runners with critical issues. Attempt to fix?`}))return;for(let i of r){if(console.log(),h.info(`Attempting to fix runner ${i.runner}...`),!i.checks.process&&i.checks.configuration){h.info("Attempting to restart runner...");try{let s=F(o.directory,"machines",i.runner);await lt`cd ${s} && ./run.sh`.quiet(),h.success(`Runner ${i.runner} restarted successfully`)}catch(s){h.error(`Failed to restart runner ${i.runner}`)}}if(!i.checks.configuration)h.warning(`Runner ${i.runner} needs to be reconfigured. Run 'hydra create' to set up again.`)}}function ie(n){let r=new Date().getTime()-n.getTime(),e=Math.floor(r/3600000);if(e<1)return`${Math.floor(r/60000)}m ago`;if(e<24)return`${e}h ago`;return`${Math.floor(e/24)}d ago`}var po="0.5.0";var uo={backup:`
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
--
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
hydra
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Restore from backup
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
`,create:`
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-n, --name Runner name prefix [string]
|
|
96
|
-
-l, --labels Comma-separated runner labels [string]
|
|
97
|
-
-o, --os Runner OS [string] (default: osx)
|
|
98
|
-
-d, --directory Runners directory [string]
|
|
99
|
-
-O, --overwrite Overwrite existing runners [boolean]
|
|
100
|
-
-p, --profile Configuration profile [string]
|
|
101
|
-
-c, --config Configuration file path [string]
|
|
102
|
-
|
|
103
|
-
EXAMPLES
|
|
104
|
-
# Create a single runner
|
|
105
|
-
hydra create -t TOKEN -u https://github.com/org/repo
|
|
106
|
-
|
|
107
|
-
# Create 3 runners with labels
|
|
108
|
-
hydra create -m 3 -t TOKEN -u URL -l docker,gpu
|
|
109
|
-
|
|
110
|
-
# Create using profile
|
|
111
|
-
hydra create -p production -t TOKEN
|
|
112
|
-
`,health:`
|
|
113
|
-
hydra health - Check runner health and diagnose issues
|
|
114
|
-
|
|
115
|
-
USAGE
|
|
116
|
-
hydra health [options]
|
|
117
|
-
|
|
118
|
-
OPTIONS
|
|
119
|
-
-d, --directory Runners directory [string]
|
|
120
|
-
-r, --runner Specific runner ID [string]
|
|
121
|
-
-t, --token GitHub Personal Access Token [string]
|
|
122
|
-
-u, --url GitHub repository or org URL [string]
|
|
123
|
-
-f, --fix Attempt to fix issues [boolean]
|
|
124
|
-
-j, --json Output in JSON format [boolean]
|
|
125
|
-
-p, --profile Configuration profile [string]
|
|
126
|
-
-c, --config Configuration file path [string]
|
|
127
|
-
|
|
128
|
-
EXAMPLES
|
|
129
|
-
# Check health of all runners
|
|
130
|
-
hydra health
|
|
131
|
-
|
|
132
|
-
# Check specific runner
|
|
133
|
-
hydra health --runner 1
|
|
134
|
-
|
|
135
|
-
# Check with GitHub connectivity test
|
|
136
|
-
hydra health -t TOKEN -u URL
|
|
137
|
-
|
|
138
|
-
# Attempt to fix issues
|
|
139
|
-
hydra health --fix
|
|
140
|
-
|
|
141
|
-
# Output as JSON
|
|
142
|
-
hydra health --json
|
|
143
|
-
`,init:`
|
|
144
|
-
hydra init - Initialize a new Hydra configuration file
|
|
145
|
-
|
|
146
|
-
USAGE
|
|
147
|
-
hydra init [options]
|
|
148
|
-
|
|
149
|
-
OPTIONS
|
|
150
|
-
-t, --toml Use TOML format instead of JSON [boolean]
|
|
151
|
-
|
|
152
|
-
EXAMPLES
|
|
153
|
-
# Initialize with interactive prompts
|
|
154
|
-
hydra init
|
|
155
|
-
|
|
156
|
-
# Initialize with TOML format
|
|
157
|
-
hydra init --toml
|
|
158
|
-
`,logs:`
|
|
159
|
-
hydra logs - View runner logs and diagnostics
|
|
160
|
-
|
|
161
|
-
USAGE
|
|
162
|
-
hydra logs [options]
|
|
163
|
-
|
|
164
|
-
OPTIONS
|
|
165
|
-
-d, --directory Runners directory [string]
|
|
166
|
-
-l, --list List all available logs [boolean]
|
|
167
|
-
-r, --runner Specific runner ID [string]
|
|
168
|
-
-t, --type Log type (runner/worker/actions) [string]
|
|
169
|
-
-p, --profile Configuration profile [string]
|
|
170
|
-
-c, --config Configuration file path [string]
|
|
171
|
-
|
|
172
|
-
EXAMPLES
|
|
173
|
-
# View logs interactively
|
|
174
|
-
hydra logs
|
|
175
|
-
|
|
176
|
-
# List all available logs
|
|
177
|
-
hydra logs --list
|
|
178
|
-
|
|
179
|
-
# View specific runner's log
|
|
180
|
-
hydra logs --runner 1 --type runner
|
|
181
|
-
|
|
182
|
-
# View logs using profile
|
|
183
|
-
hydra logs -p production
|
|
184
|
-
`,remove:`
|
|
185
|
-
hydra remove - Remove GitHub runner machines
|
|
186
|
-
|
|
187
|
-
USAGE
|
|
188
|
-
hydra remove [options]
|
|
189
|
-
|
|
190
|
-
OPTIONS
|
|
191
|
-
-t, --token GitHub Personal Access Token [string] (required)
|
|
192
|
-
-u, --url GitHub repository or org URL [string] (required)
|
|
193
|
-
-m, --numberOfMachines Number of machines [number] (default: 1)
|
|
194
|
-
-n, --name Runner name prefix [string]
|
|
195
|
-
-d, --directory Runners directory [string]
|
|
196
|
-
-f, --force Force removal [boolean]
|
|
197
|
-
-p, --profile Configuration profile [string]
|
|
198
|
-
-c, --config Configuration file path [string]
|
|
199
|
-
|
|
200
|
-
EXAMPLES
|
|
201
|
-
# Remove and unregister
|
|
202
|
-
hydra remove -t TOKEN -u https://github.com/org/repo
|
|
203
|
-
|
|
204
|
-
# Force remove
|
|
205
|
-
hydra remove -m 2 --force
|
|
206
|
-
|
|
207
|
-
# Remove specific runners
|
|
208
|
-
hydra remove -n custom -m 3 -t TOKEN -u URL
|
|
209
|
-
`,run:`
|
|
210
|
-
hydra run - Start existing GitHub runner machines
|
|
211
|
-
|
|
212
|
-
USAGE
|
|
213
|
-
hydra run [options]
|
|
214
|
-
|
|
215
|
-
OPTIONS
|
|
216
|
-
-t, --token GitHub Personal Access Token [string] (required)
|
|
217
|
-
-u, --url GitHub repository or org URL [string] (required)
|
|
218
|
-
-m, --numberOfMachines Number of machines [number] (default: 1)
|
|
219
|
-
-n, --name Runner name prefix [string]
|
|
220
|
-
-d, --directory Runners directory [string]
|
|
221
|
-
-p, --profile Configuration profile [string]
|
|
222
|
-
-c, --config Configuration file path [string]
|
|
223
|
-
|
|
224
|
-
EXAMPLES
|
|
225
|
-
# Run existing runners
|
|
226
|
-
hydra run -t TOKEN -u https://github.com/org/repo
|
|
227
|
-
|
|
228
|
-
# Run specific runners
|
|
229
|
-
hydra run -m 2 -n custom -t TOKEN -u URL
|
|
230
|
-
`,scale:`
|
|
231
|
-
hydra scale - Automatically scale runners based on job queue
|
|
232
|
-
|
|
233
|
-
USAGE
|
|
234
|
-
hydra scale [options]
|
|
235
|
-
|
|
236
|
-
OPTIONS
|
|
237
|
-
-t, --token GitHub Personal Access Token [string] (required)
|
|
238
|
-
-u, --url GitHub repository or org URL [string] (required)
|
|
239
|
-
-m, --min Minimum number of runners [number] (default: 1)
|
|
240
|
-
-M, --max Maximum number of runners [number] (default: 5)
|
|
241
|
-
-w, --watch Watch mode - continuous scaling [boolean]
|
|
242
|
-
-i, --interval Check interval in seconds [number] (default: 60)
|
|
243
|
-
--scale-up-threshold Jobs in queue to trigger scale up [number] (default: 2)
|
|
244
|
-
--scale-down-idle Minutes idle before scale down [number] (default: 30)
|
|
245
|
-
--dry Preview actions without changes [boolean]
|
|
246
|
-
-d, --directory Runners directory [string]
|
|
247
|
-
-p, --profile Configuration profile [string]
|
|
248
|
-
-c, --config Configuration file path [string]
|
|
249
|
-
|
|
250
|
-
EXAMPLES
|
|
251
|
-
# Check and scale once
|
|
252
|
-
hydra scale -t TOKEN -u URL
|
|
253
|
-
|
|
254
|
-
# Watch mode with custom thresholds
|
|
255
|
-
hydra scale -t TOKEN -u URL --watch --min 2 --max 10
|
|
256
|
-
|
|
257
|
-
# Scale with faster response time
|
|
258
|
-
hydra scale -t TOKEN -u URL -w -i 30 --scale-up-threshold 1
|
|
259
|
-
|
|
260
|
-
# Preview scaling decisions
|
|
261
|
-
hydra scale -t TOKEN -u URL --dry
|
|
262
|
-
|
|
263
|
-
NOTES
|
|
264
|
-
- Monitors GitHub job queue and automatically adjusts runner count
|
|
265
|
-
- Scale up when pending jobs exceed threshold
|
|
266
|
-
- Scale down when runners are idle for specified duration
|
|
267
|
-
- Respects min/max limits to control costs
|
|
268
|
-
- Watch mode runs continuously until stopped (Ctrl+C)
|
|
269
|
-
`,status:`
|
|
270
|
-
hydra status - Check the status of GitHub runner machines
|
|
271
|
-
|
|
272
|
-
USAGE
|
|
273
|
-
hydra status [options]
|
|
274
|
-
|
|
275
|
-
OPTIONS
|
|
276
|
-
-t, --token GitHub Personal Access Token [string] (required)
|
|
277
|
-
-u, --url GitHub repository or org URL [string] (required)
|
|
278
|
-
-d, --directory Runners directory [string]
|
|
279
|
-
-j, --json Output status in JSON format [boolean]
|
|
280
|
-
-p, --profile Configuration profile [string]
|
|
281
|
-
-c, --config Configuration file path [string]
|
|
282
|
-
|
|
283
|
-
EXAMPLES
|
|
284
|
-
# Check runner status
|
|
285
|
-
hydra status -t TOKEN -u https://github.com/org/repo
|
|
286
|
-
|
|
287
|
-
# Output as JSON
|
|
288
|
-
hydra status -t TOKEN -u URL --json
|
|
289
|
-
|
|
290
|
-
# Status using profile
|
|
291
|
-
hydra status -p production
|
|
292
|
-
`};function wn(n){if(n&&uo[n]){let r=uo[n].split(`
|
|
293
|
-
`).map((e)=>{if(e.startsWith("hydra"))return p.bold(e);if(e==="USAGE"||e==="OPTIONS"||e==="EXAMPLES")return p.bold(e);if(e.startsWith(" -")){let i=e.match(/^(\s+-\w,\s--\w+)\s+(.+)$/);if(i){let[,s="",t=""]=i,f=t.replace("(required)",p.error("(required)")).replace(/\(default: ([^)]+)\)/g,(a,c)=>p.dim(`(default: ${c})`)).replace(/\[boolean\]/g,p.boolean("[boolean]")).replace(/\[string\]/g,p.string("[string]")).replace(/\[number\]/g,p.number("[number]"));return` ${p.flag(s.padEnd(26))} ${f}`}}if(e.startsWith(" # "))return p.dim(e);if(e.startsWith(" hydra"))return` ${p.value(e.trim())}`;return e}).join(`
|
|
294
|
-
`);console.info(r);return}console.info(`
|
|
295
|
-
${p.bold(`Hydra@${po} - GitHub self-hosted runner manager`)}
|
|
296
|
-
|
|
297
|
-
${p.bold("USAGE")}
|
|
298
|
-
hydra <command> [options]
|
|
299
|
-
|
|
300
|
-
${p.bold("COMMANDS")}
|
|
301
|
-
${p.command("init")} Initialize a new Hydra configuration file
|
|
302
|
-
${p.command("create")} Create and register new GitHub runner machines
|
|
303
|
-
${p.command("run")} Start existing GitHub runner machines
|
|
304
|
-
${p.command("remove")} Remove GitHub runner machines
|
|
305
|
-
${p.command("status")} Check the status of GitHub runner machines
|
|
306
|
-
${p.command("logs")} View runner logs and diagnostics
|
|
307
|
-
${p.command("health")} Check runner health and diagnose issues
|
|
308
|
-
${p.command("scale")} Automatically scale runners based on job queue
|
|
309
|
-
${p.command("backup")} Backup and restore runner configurations
|
|
310
|
-
${p.command("help")} Show this help message
|
|
311
|
-
|
|
312
|
-
Use ${p.value("hydra <command> --help")} for more information about a command.
|
|
313
|
-
`)}import{resolve as fe}from"path";import{parseArgs as ae}from"util";var{$:pt}=globalThis.Bun;var en=x({prefix:"hydra"}).child("init");async function go(){let{toml:n}=me(),o=n?"hydra.toml":"hydra.json",r=fe(process.cwd(),o);if(await Bun.file(r).exists()){let l=await C({initialValue:!1,message:`Configuration file ${o} already exists. Overwrite?`});if(U(l)||!l)it("Configuration cancelled"),process.exit(0)}Bt(w.cyan("\uD83D\uDE80 Hydra Configuration Setup")),en.info("This will create a configuration file with your runner settings."),en.info("You can always edit the file later or create additional profiles.");let i=await It({profileName:()=>q({message:"Profile name?",placeholder:"default"}),directory:()=>q({defaultValue:"./gh-runners",message:"Directory to store runners?",placeholder:"./gh-runners"}),name:()=>q({defaultValue:"runner",message:"Runner name prefix?",placeholder:"runner"}),labels:({results:l})=>{let u=l.name||"runner";return q({defaultValue:u,message:"Runner labels (comma-separated)?",placeholder:u})},numberOfMachines:()=>q({defaultValue:"1",message:"Number of runner machines?",placeholder:"1",validate:(l)=>{let u=Number.parseInt(l,10);if(Number.isNaN(u)||u<1)return"Please enter a valid number greater than 0";return}}),url:()=>q({message:"GitHub repository or organization URL? (optional)",placeholder:"https://github.com/org/repo"})},{onCancel:()=>{it("Configuration cancelled"),process.exit(0)}}),{profileName:s,labels:t,numberOfMachines:f,...a}=i,c={defaultProfile:s,profiles:{[s]:{...a,labels:t,numberOfMachines:Number.parseInt(f,10),os:"osx",overwrite:!1,run:!1}}},m=JSON.stringify(c,null,2);if(await Bun.write(r,m),await an(async()=>{await pt`chmod 600 ${r}`.quiet()},{logLevel:"warn",message:"Could not set secure file permissions"}),Wt(w.green(`\u2713 Configuration saved to ${o}`)),en.info("Example usage:"),en.info(` hydra create -p ${s} --token YOUR_TOKEN${i.url?"":" --url REPO_URL"}`),en.info("You can add more profiles by editing the configuration file."),i.url)await ce(i.url)}async function ce(n){let o=/github\.com[:/]([^/]+)(?:\/([^/.]+))?/,r=n.match(o);if(!r)return;let[,e,i]=r,t=`https://github.com/${i?`${e}/${i}`:`organizations/${e}`}/settings/actions/runners`;en.info(`Opening GitHub settings: ${t}`),await an(async()=>{await pt`open ${t}`.quiet()},{fallback:async()=>{await an(async()=>{await pt`xdg-open ${t}`.quiet()},{fallback:()=>{en.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"})}function me(){let{values:n}=ae({allowPositionals:!0,args:Bun.argv,options:{toml:{default:!1,short:"t",type:"boolean"}},strict:!0});return n}import{existsSync as ho}from"fs";import{readdir as bo}from"fs/promises";import{join as vn,resolve as le}from"path";import{parseArgs as pe}from"util";var ue=x({prefix:"hydra"}).child("logs");async function de(){let{values:n}=pe({allowPositionals:!0,args:Bun.argv,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},list:{default:!1,short:"l",type:"boolean"},profile:{short:"p",type:"string"},runner:{short:"r",type:"string"},type:{short:"t",type:"string"}},strict:!0}),o=await A({configPath:n.config}),r=await X(o,n.profile);return{directory:n.directory||r?.directory||`${process.cwd()}/gh-runners`,list:n.list,runner:n.runner,type:n.type}}async function yo(){try{let n=await de(),o=le(n.directory),r=vn(o,"machines");if(!ho(r)){h.error(`No runners found in ${n.directory}`);return}let e=W();e.start("Scanning for runner logs...");let i=await bo(r),s=[];for(let f of i){let a=vn(r,f),c=vn(a,"_diag");if(ho(c)){let m=await ge(c);if(m.length>0)s.push({logs:m,runner:f})}}if(e.stop("Found runner logs"),s.length===0){h.info("No log files found");return}if(n.list){he(s);return}if(n.runner&&n.type){await ye(s,n.runner,n.type);return}let t=await be(s);if(t)await wo(t)}catch(n){ue.error("Failed to retrieve logs:",n),process.exit(1)}}async function ge(n){let o=await bo(n),r=[];for(let e of o)if(e.endsWith(".log")){let i=vn(n,e),s=await Bun.file(i).stat();r.push({modified:new Date(s.mtime),name:e,path:i,size:s.size})}return r.sort((e,i)=>i.modified.getTime()-e.modified.getTime())}function he(n){console.log(p.bold(`
|
|
314
|
-
\uD83D\uDCCB Available Logs
|
|
315
|
-
`));for(let{runner:o,logs:r}of n){console.log(`${p.bold(`Runner ${o}:`)}`);for(let e of r){let i=ut(e.size),s=dt(e.modified),t=Hn(e.name);console.log(` ${p.value(t.padEnd(20))} ${p.dim(i.padEnd(10))} ${p.dim(s)}`)}console.log()}}async function be(n){let o=[];for(let{runner:e,logs:i}of n)for(let s of i)o.push({hint:`${ut(s.size)} - ${dt(s.modified)}`,label:`Runner ${e} - ${Hn(s.name)}`,value:s});return await Gn({message:"Select a log file to view",options:o})}async function ye(n,o,r){let e=n.find(({runner:s})=>s===o);if(!e){h.error(`Runner ${o} not found`);return}let i=e.logs.find((s)=>Hn(s.name).toLowerCase().includes(r.toLowerCase()));if(!i){h.error(`Log type '${r}' not found for runner ${o}`);return}await wo(i)}async function wo(n){console.log(),console.log(p.bold(`\uD83D\uDCC4 ${Hn(n.name)}`)),console.log(p.dim(`Size: ${ut(n.size)} | Modified: ${dt(n.modified)}`)),console.log(p.dim("\u2500".repeat(80))),console.log();let o=await Bun.file(n.path).text(),r=o.split(`
|
|
316
|
-
`);if(r.length>100){let e=r.slice(-100);console.log(p.dim(`... (showing last 100 lines of ${r.length} total)
|
|
317
|
-
`)),console.log(e.join(`
|
|
318
|
-
`))}else console.log(o)}function Hn(n){if(n.includes("Runner_"))return"Runner Log";if(n.includes("Worker_"))return"Worker Log";if(n.includes("Actions"))return"Actions Log";if(n.includes("Listener"))return"Listener Log";return n.replace(".log","")}function ut(n){if(n<1024)return`${n}B`;if(n<1048576)return`${(n/1024).toFixed(1)}KB`;return`${(n/1048576).toFixed(1)}MB`}function dt(n){let r=new Date().getTime()-n.getTime(),e=Math.floor(r/3600000);if(e<1)return`${Math.floor(r/60000)}m ago`;if(e<24)return`${e}h ago`;let i=Math.floor(e/24);if(i<7)return`${i}d ago`;return n.toLocaleDateString()}import{parseArgs as we}from"util";var{$:sn}=globalThis.Bun;var K=x({prefix:"hydra"}).child("remove");async function Pn(){let n=await xe(),{directory:o,numberOfMachines:r,force:e}=n,{token:i,url:s}=n,t=`${o}/machines`;if(!await Bun.file(t).exists())throw new Error(`Machines directory not found at ${t}. Nothing to remove.`);if(!i&&!e){if(!s)throw K.warn("No token or URL provided. Runners will not be unregistered from GitHub."),K.warn("Use --force to remove runners without unregistering them."),new Error("Token (-t) and URL (-u) parameters are required or use --force");let a=Oe(s),c=await C({message:`No token provided. Would you like to open GitHub to get a runner token for unregistration?
|
|
319
|
-
${a}`});if(U(c)||!c)throw K.warn("Use --force to remove runners without unregistering them."),new Error("Token is required to unregister runners (or use --force)");K.info("Opening GitHub runner settings..."),await sn`open ${a}`.quiet();let m=await q({message:"Enter the runner removal token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(l)=>{if(!l||l.trim().length===0)return"Token is required";return}});if(U(m))throw K.warn("Use --force to remove runners without unregistering them."),new Error("Token is required to unregister runners (or use --force)");i=m.trim()}if(i&&s)K.info("Unregistering runners from GitHub..."),await $e({directory:o,numberOfMachines:r,token:i});else if(!e)throw K.warn("No token or URL provided. Runners will not be unregistered from GitHub."),K.warn("Use --force to remove runners without unregistering them."),new Error("Token (-t) and URL (-u) parameters are required or use --force");await Ee({directory:o,numberOfMachines:r}),K.info("Runners successfully removed")}async function xe(){let{values:n}=we({allowPositionals:!0,args:Bun.argv,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 A({configPath:n.config}),r=await X(o,n.profile),e={directory:n.directory,force:n.force,numberOfMachines:n.numberOfMachines,token:n.token,url:n.url};if(r)return{directory:e.directory??r.directory??`${process.cwd()}/gh-runners`,force:e.force,numberOfMachines:e.numberOfMachines??String(r.numberOfMachines)??"1",token:e.token,url:e.url??r.url};return e}async function $e({directory:n,numberOfMachines:o,token:r}){let e=K.child("unregister"),i=Number(o),s=(()=>{try{let u=Bun.spawnSync(["nproc"]);return Number.parseInt(u.stdout.toString().trim(),10)||4}catch{try{let u=Bun.spawnSync(["sysctl","-n","hw.ncpu"]);return Number.parseInt(u.stdout.toString().trim(),10)||4}catch{return 4}}})(),t=Math.min(Math.max(2,Math.floor(s/2)),i,8);e.info(`Unregistering ${i} runners with concurrency of ${t}`);let f=Array.from({length:i},(u,b)=>b+1).map((u)=>({execute:async()=>{let b=`${n}/machines/${u}`;if(!await Bun.file(b).exists())return e.debug(`Machine ${u} doesn't exist, skipping...`),{runnerIndex:u,status:"skipped"};try{return e.debug(`Unregistering machine ${u}...`),await sn`${b}/config.sh remove --token ${r}`.quiet(),e.info(`Successfully unregistered machine ${u} from GitHub`),{runnerIndex:u,status:"success"}}catch($){return e.warn(`Unable to unregister machine ${u}: ${$}`),{error:$,runnerIndex:u,status:"failed"}}},runnerIndex:u})),a=[];for(let u=0;u<f.length;u+=t){let b=f.slice(u,u+t),g=await Promise.allSettled(b.map(($)=>$.execute()));a.push(...g)}let c=a.filter((u)=>u.status==="fulfilled"&&u.value?.status==="success").length,m=a.filter((u)=>u.status==="fulfilled"&&u.value?.status==="failed").length,l=a.filter((u)=>u.status==="fulfilled"&&u.value?.status==="skipped").length;e.info(`Unregistration complete: ${c} successful, ${m} failed, ${l} skipped`)}async function Ee({directory:n,numberOfMachines:o}){let r=K.child("removeDirectories"),e=Number(o),i=Array.from({length:e},(a,c)=>c+1).map((a)=>({execute:async()=>{let c=`${n}/machines/${a}`;if(!await Bun.file(c).exists())return{runnerIndex:a,status:"skipped"};try{return await sn`rm -rf ${c}`.quiet(),r.debug(`Removed machine ${a} directory`),{runnerIndex:a,status:"success"}}catch(l){return r.error(`Error removing machine ${a} directory: ${l}`),{error:l,runnerIndex:a,status:"failed"}}},runnerIndex:a})),s=await Promise.allSettled(i.map((a)=>a.execute())),t=s.filter((a)=>a.status==="fulfilled"&&a.value?.status==="success").length,f=s.filter((a)=>a.status==="fulfilled"&&a.value?.status==="failed").length;if(r.info(`Directory removal complete: ${t} removed, ${f} failed`),f>0)throw new Error(`Failed to remove ${f} runner directories`);try{let a=`${n}/machines`;if(!(await sn`ls -A ${a}`.text()).trim()){if(await sn`rm -rf ${a}`.quiet(),!(await sn`ls -A ${n}`.text()).trim())await sn`rm -rf ${n}`.quiet();K.info("Removed empty directories")}}catch(a){}}function Oe(n){try{let o=new URL(n),r=o.pathname.split("/").filter(Boolean);if(o.hostname==="github.com"||o.hostname==="www.github.com"){if(r[0]==="orgs"&&r[1])return`https://github.com/organizations/${r[1]}/settings/actions/runners`;else if(r.length>=2)return`https://github.com/${r[0]}/${r[1]}/settings/actions/runners`}else if(r[0]==="orgs"&&r[1])return`${o.origin}/organizations/${r[1]}/settings/actions/runners`;else if(r.length>=2)return`${o.origin}/${r[0]}/${r[1]}/settings/actions/runners`;return n}catch{return n}}import{parseArgs as Re}from"util";var{$:Se}=globalThis.Bun;var J=x({prefix:"runMachines"});async function xo(){let n=await Te(),{directory:o,numberOfMachines:r,name:e,labels:i,runnerGroup:s}=n,{token:t,url:f}=n;if(!f)throw new Error("URL (-u) parameter is required");if(!t){let c=Ne(f),m=await C({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
320
|
-
${c}`});if(U(m)||!m)throw new Error("Token is required to run machines");J.info("Opening GitHub runner settings..."),await Se`open ${c}`.quiet();let l=await q({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(u)=>{if(!u||u.trim().length===0)return"Token is required";return}});if(U(l))throw new Error("Token is required to run machines");t=l.trim()}if(J.info(`Starting ${r} runners from ${o}`),J.debug(`Name: ${e}, Labels: ${i||"none"}`),!await Bun.file(`${o}/machines`).exists())throw new Error(`Machines directory not found at ${o}/machines. Run 'hydra create' first.`);await Le({directory:o,labels:i,name:e,numberOfMachines:r,runnerGroup:s,token:t,url:f})}async function Te(){let{values:n}=Re({allowPositionals:!0,args:Bun.argv,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 A({configPath:n.config}),r=await X(o,n.profile),e={directory:n.directory,labels:n.labels,name:n.name,numberOfMachines:n.numberOfMachines,runnerGroup:n.runnerGroup,token:n.token,url:n.url};if(r)return{directory:e.directory??r.directory??`${process.cwd()}/gh-runners`,labels:e.labels??r.labels,name:e.name??r.name??"runner",numberOfMachines:e.numberOfMachines??String(r.numberOfMachines)??"1",runnerGroup:e.runnerGroup??r.runnerGroup,token:e.token,url:e.url??r.url};return e}async function Le({directory:n,numberOfMachines:o,token:r,url:e,name:i,labels:s,runnerGroup:t}){J.info(`Starting ${o} workers...`);for(let f=1;f<=Number(o);f++){let a=`${n}/machines/${f}`;if(!await Bun.file(a).exists()){J.warn(`Machine ${f} doesn't exist, skipping...`);continue}let m=`${bn()}/src/runner-worker.ts`,l=`${i}-${f}`,u=new Worker(m,{name:l,ref:!0});u.addEventListener("message",({data:b})=>{let g=b.type==="error"?"error":"info";J[g](`${l}: ${b.message}`)}),u.addEventListener("error",(b)=>{J.error(`Worker ${l} error:`,b)}),u.addEventListener("exit",(b)=>{J.info(`Worker ${l} exited with code ${b}`)}),u.postMessage({index:f,labels:s,machineCwd:a,name:i,runnerGroup:t,token:r,url:e}),J.info(`Worker ${l} starting...`),qn.add(u)}J.info("All workers started. Press Ctrl+C to stop all machines")}function Ne(n){try{let o=new URL(n),r=o.pathname.split("/").filter(Boolean);if(o.hostname==="github.com"||o.hostname==="www.github.com"){if(r[0]==="orgs"&&r[1])return`https://github.com/organizations/${r[1]}/settings/actions/runners/new`;else if(r.length>=2)return`https://github.com/${r[0]}/${r[1]}/settings/actions/runners/new`}else if(r[0]==="orgs"&&r[1])return`${o.origin}/organizations/${r[1]}/settings/actions/runners/new`;else if(r.length>=2)return`${o.origin}/${r[0]}/${r[1]}/settings/actions/runners/new`;return n}catch{return n}}import{parseArgs as Ge}from"util";var $o=x({prefix:"hydra"}).child("scale");async function Ae(){let{values:n}=Ge({allowPositionals:!0,args:Bun.argv,options:{config:{short:"c",type:"string"},directory:{default:`${process.cwd()}/gh-runners`,short:"d",type:"string"},dry:{default:!1,type:"boolean"},interval:{default:"60",short:"i",type:"string"},max:{default:"5",short:"M",type:"string"},min:{default:"1",short:"m",type:"string"},profile:{short:"p",type:"string"},"scale-down-idle":{default:"30",type:"string"},"scale-up-threshold":{default:"2",type:"string"},token:{short:"t",type:"string"},url:{short:"u",type:"string"},watch:{default:!1,short:"w",type:"boolean"}},strict:!0}),o=await A({configPath:n.config}),r=await X(o,n.profile);return{directory:n.directory||r?.directory||`${process.cwd()}/gh-runners`,dry:n.dry,scaleConfig:{checkIntervalSeconds:parseInt(n.interval,10),maxRunners:parseInt(n.max,10),minRunners:parseInt(n.min,10),scaleDownIdleMinutes:parseInt(n["scale-down-idle"],10),scaleUpThreshold:parseInt(n["scale-up-threshold"],10)},token:n.token,url:n.url||r?.url,watch:n.watch}}async function Eo(){try{let n=await Ae();if(!n.token||!n.url)throw new Error("Token (-t) and URL (-u) parameters are required");if(n.scaleConfig.minRunners>n.scaleConfig.maxRunners)throw new Error("Minimum runners cannot be greater than maximum runners");if(h.info("Autoscale Configuration:"),console.log(` Min Runners: ${p.value(String(n.scaleConfig.minRunners))}`),console.log(` Max Runners: ${p.value(String(n.scaleConfig.maxRunners))}`),console.log(` Scale Up Threshold: ${p.value(String(n.scaleConfig.scaleUpThreshold))} pending jobs`),console.log(` Scale Down After: ${p.value(String(n.scaleConfig.scaleDownIdleMinutes))} minutes idle`),console.log(),n.watch)await _e(n);else await Xe(n)}catch(n){$o.error("Failed to scale runners:",n),process.exit(1)}}async function Xe(n){let o=W();o.start("Analyzing queue and runners...");try{let r=await Oo(n.url,n.token,n.directory);o.stop("Analysis complete"),Ce(r);let e=Ro(r,n.scaleConfig);if(e.type==="none"){h.info("No scaling action needed");return}if(console.log(),e.type==="scale-up")h.info(`Recommendation: Scale UP by ${e.count} runner(s)`),h.info(`Reason: ${e.reason}`);else h.info(`Recommendation: Scale DOWN by ${e.count} runner(s)`),h.info(`Reason: ${e.reason}`);if(n.dry){h.info("Dry run - no changes made");return}if(!await C({initialValue:!0,message:`Proceed with ${e.type}?`})){h.info("Cancelled");return}await So(e,n)}catch(r){throw o.stop("Failed"),r}}async function _e(n){h.info(`Starting autoscale watch mode (checking every ${n.scaleConfig.checkIntervalSeconds}s)`),console.log(`Press Ctrl+C to stop
|
|
321
|
-
`);let o=new Map;while(!0)try{let r=await Oo(n.url,n.token,n.directory);await qe(o,r,n);let e=Ro(r,n.scaleConfig,o),i=new Date().toLocaleTimeString();if(console.log(`[${i}] Queue: ${r.pendingJobs} | Active: ${r.activeRunners} | Idle: ${r.idleRunners} | Total: ${r.totalRunners}`),e.type!=="none"){if(console.log(`[${i}] ${p.warning(`Action: ${e.type} by ${e.count} - ${e.reason}`)}`),!n.dry)await So(e,n)}await Bun.sleep(n.scaleConfig.checkIntervalSeconds*1000)}catch(r){$o.error("Error in watch cycle:",r),await Bun.sleep(n.scaleConfig.checkIntervalSeconds*1000)}}async function Oo(n,o,r){let e=await Ue(n,o),i=await gt(n,o,r),s=i.filter((a)=>a.busy).length,t=i.filter((a)=>a.status==="online"&&!a.busy).length,f=i.length;return{activeRunners:s,idleRunners:t,pendingJobs:e,totalRunners:f}}async function Ue(n,o){let r=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!r)throw new Error("Invalid GitHub URL");let[,e,i]=r,s=i?`https://api.github.com/repos/${e}/${i}/actions/runs?status=queued&per_page=100`:`https://api.github.com/orgs/${e}/actions/runs?status=queued&per_page=100`;return Z(async()=>{let t=await fetch(s,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${o}`}});if(!t.ok)throw new Error(`GitHub API error: ${t.status}`);let f=await t.json(),a=0;for(let c of f.workflow_runs||[]){let m=await fetch(`https://api.github.com/repos/${e}/${i}/actions/runs/${c.id}/jobs`,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${o}`}});if(m.ok){let l=await m.json();a+=l.jobs?.filter((u)=>u.status==="queued").length||0}}return a},{maxAttempts:3})}async function gt(n,o,r){let e=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!e)return[];let[,i,s]=e,t=s?`https://api.github.com/repos/${i}/${s}/actions/runners`:`https://api.github.com/orgs/${i}/actions/runners`,f=await fetch(t,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${o}`}});if(!f.ok)return[];return(await f.json()).runners||[]}function Ro(n,o,r){if(n.pendingJobs>=o.scaleUpThreshold&&n.totalRunners<o.maxRunners)return{count:Math.min(n.totalRunners+Math.ceil(n.pendingJobs/2),o.maxRunners)-n.totalRunners,reason:`${n.pendingJobs} jobs pending (threshold: ${o.scaleUpThreshold})`,type:"scale-up"};if(n.idleRunners>0&&n.totalRunners>o.minRunners){let e=0;if(r){let i=new Date;for(let[,s]of r)if((i.getTime()-s.getTime())/60000>=o.scaleDownIdleMinutes)e++}else e=n.idleRunners;if(e>0)return{count:Math.min(e,n.totalRunners-o.minRunners),reason:`${e} runners idle for ${o.scaleDownIdleMinutes}+ minutes`,type:"scale-down"}}return{count:0,reason:"",type:"none"}}async function So(n,o){if(n.type==="scale-up"){h.info(`Scaling up by ${n.count} runner(s)...`);let r=process.argv;try{process.argv=[process.argv[0],process.argv[1],"create","-t",o.token,"-u",o.url,"-m",String(n.count),"-d",o.directory],await Cn(),h.success(`Successfully added ${n.count} runner(s)`)}finally{process.argv=r}}else if(n.type==="scale-down"){h.info(`Scaling down by ${n.count} runner(s)...`);let e=(await gt(o.url,o.token,o.directory)).filter((s)=>s.status==="online"&&!s.busy).slice(0,n.count);if(e.length===0){h.warning("No idle runners to remove");return}let i=process.argv;try{for(let s of e){let t=s.name.match(/runner-(\d+)/)?.[1];if(!t)continue;process.argv=[process.argv[0],process.argv[1],"remove","-t",o.token,"-u",o.url,"-n",`runner-${t}`,"-d",o.directory,"-f"],await Pn()}h.success(`Successfully removed ${e.length} runner(s)`)}finally{process.argv=i}}}async function qe(n,o,r){let e=await gt(r.url,r.token,r.directory);for(let s of e)if(s.status==="online"&&!s.busy){if(!n.has(s.name))n.set(s.name,new Date)}else n.delete(s.name);let i=new Set(e.map((s)=>s.name));for(let[s]of n)if(!i.has(s))n.delete(s)}function Ce(n){console.log(),console.log(p.bold("\uD83D\uDCCA Current Status")),console.log(` Pending Jobs: ${p.value(String(n.pendingJobs))}`),console.log(` Total Runners: ${p.value(String(n.totalRunners))}`),console.log(` Active Runners: ${p.success(String(n.activeRunners))}`),console.log(` Idle Runners: ${p.warning(String(n.idleRunners))}`)}import{parseArgs as ve}from"util";var{$:He}=globalThis.Bun;var un=x({prefix:"hydra"}).child("status");async function To(){let n=await Pe(),{directory:o,token:r,url:e,json:i}=n;if(!r||!e)throw new Error("Token (-t) and URL (-u) parameters are required");let s=W();s.start("Fetching runner status...");try{let t=await Me(o),f=await Be(e,r),a=We(t,f);if(s.stop("Runner status fetched"),i)un.info(JSON.stringify(a,null,2));else Ie(a)}catch(t){throw s.stop("Failed to fetch runner status"),t}}async function Pe(){let{values:n}=ve({allowPositionals:!0,args:Bun.argv,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 A({configPath:n.config}),r=await X(o,n.profile);return{directory:n.directory||r?.directory||`${process.cwd()}/gh-runners`,json:n.json,token:n.token,url:n.url||r?.url}}async function Me(n){let o=`${n}/machines`;return await an(async()=>{return(await He`ls ${o} 2>/dev/null || true`.quiet()).stdout.toString().trim().split(`
|
|
322
|
-
`).filter(Boolean)},{fallback:()=>{},logLevel:"debug",message:"No local runners found"})||[]}async function Be(n,o){let r=n.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!r)throw new Error("Invalid GitHub URL");let[,e,i]=r,s=i?`https://api.github.com/repos/${e}/${i}/actions/runners`:`https://api.github.com/orgs/${e}/actions/runners`;return Z(async()=>{let t={Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${o}`},f=await fetch(s,{headers:t});if(!f.ok)throw new Error(`GitHub API error: ${f.status} ${f.statusText}`);return await f.json()},{onRetry:(t,f)=>{h.warn(`Retrying GitHub API call (attempt ${t}): ${f.message}`)}})}function We(n,o){let r=[],e=new Map(o.runners.map((i)=>[i.name,i]));for(let i of n){let s=`runner-${i}`,t=e.get(s);if(t)r.push({busy:t.busy,labels:t.labels.map((f)=>f.name),name:s,os:t.os,status:t.busy?"busy":t.status==="online"?"online":"offline"});else r.push({busy:!1,labels:[],name:s,os:"unknown",status:"offline"})}return r}function Ie(n){if(n.length===0){h.info("No runners found");return}un.info("Runner Status:"),un.info("\u2500".repeat(80));let o={busy:p.busy,offline:p.offline,online:p.online};for(let e of n){let i=o[e.status],s=e.status.toUpperCase().padEnd(7);un.info(`${i("\u25CF")} ${i(s)} ${p.value(e.name.padEnd(20))} ${p.dim(`OS: ${e.os.padEnd(10)}`)} ${e.labels.length>0?p.dim(`Labels: ${e.labels.join(", ")}`):""}`)}un.info("\u2500".repeat(80));let r={busy:n.filter((e)=>e.status==="busy").length,offline:n.filter((e)=>e.status==="offline").length,online:n.filter((e)=>e.status==="online").length,total:n.length};un.info(`Summary: Total: ${r.total} | ${p.online(`Online: ${r.online}`)} | ${p.busy(`Busy: ${r.busy}`)} | ${p.offline(`Offline: ${r.offline}`)}`)}var Mn=["init","create","run","remove","status","logs","health","scale","backup","help"],Bn=x({prefix:"hydra"}),Ke={auto:"scale",autoscale:"scale",b:"backup",back:"backup",bak:"backup",c:"create",ceate:"create",check:"health",craete:"create",cretae:"create",del:"remove",delete:"remove",diagnose:"health",h:"help",heal:"health",healthy:"health",i:"init",info:"status",initialise:"init",inti:"init",intialize:"init",l:"logs",list:"status",log:"logs",ls:"status",new:"create",r:"run",remvoe:"remove",resize:"scale",restore:"backup",rm:"remove",rmove:"remove",rnu:"run",runn:"run",s:"status",save:"backup",scal:"scale",start:"run",stat:"status",stop:"remove",sttaus:"status",t:"troubleshoot",tail:"logs"};async function ze(){try{let[,,n,...o]=process.argv;if(!n||n==="--help"||n==="-h")wn(),process.exit(0);let r=n;if(!Mn.includes(n)){let e=Yt(n,Ke);if(e&&Mn.includes(e))r=e,Bn.warn(`Assuming you meant '${e}'`)}if(!Mn.includes(r)){Bn.error(`Unknown command: ${n}`);let e=Jt(n,Mn);if(e.length>0){Bn.error("Did you mean one of these?");for(let i of e)Bn.error(` ${i}`)}wn(),process.exit(1)}if(o.includes("--help")||o.includes("-h"))wn(r),process.exit(0);switch(r){case"init":await go();break;case"create":await Cn();break;case"run":await xo();break;case"remove":await Pn();break;case"status":await To();break;case"logs":await yo();break;case"health":await lo();break;case"scale":await Eo();break;case"backup":await fo();break;case"help":{let e=o[0];wn(e);break}default:throw new Error(`Unknown command: ${r}`)}process.exit(0)}catch(n){let o=n instanceof Error?n:new Error(String(n));h.error(o.message),process.exit(1)}}await ze();
|
|
53
|
+
`)},info:(r)=>{m.message(r,{symbol:p.default.blue(Ci)})},success:(r)=>{m.message(r,{symbol:p.default.green(Wi)})},step:(r)=>{m.message(r,{symbol:p.default.green(nn)})},warn:(r)=>{m.message(r,{symbol:p.default.yellow(Mi)})},warning:(r)=>{m.warn(r)},error:(r)=>{m.message(r,{symbol:p.default.red(Gi)})}},De=`${p.default.gray(_)} `;var K=({indicator:r="dots"}={})=>{let n=Fr?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],t=Fr?80:120,o=process.env.CI==="true",e,s,i=!1,a="",f,d=performance.now(),c=(O)=>{let C=O>1?"Something went wrong":"Canceled";i&&gr(C,O)},u=()=>c(2),l=()=>c(1),R=()=>{process.on("uncaughtExceptionMonitor",u),process.on("unhandledRejection",u),process.on("SIGINT",l),process.on("SIGTERM",l),process.on("exit",c)},h=()=>{process.removeListener("uncaughtExceptionMonitor",u),process.removeListener("unhandledRejection",u),process.removeListener("SIGINT",l),process.removeListener("SIGTERM",l),process.removeListener("exit",c)},g=()=>{if(f===void 0)return;o&&process.stdout.write(`
|
|
54
|
+
`);let O=f.split(`
|
|
55
|
+
`);process.stdout.write(kr.cursor.move(-999,O.length-1)),process.stdout.write(kr.erase.down(O.length))},N=(O)=>O.replace(/\.+$/,""),nr=(O)=>{let C=(performance.now()-O)/1000,q=Math.floor(C/60),ir=Math.floor(C%60);return q>0?`[${q}m ${ir}s]`:`[${ir}s]`},tr=(O="")=>{i=!0,e=jn(),a=N(O),d=performance.now(),process.stdout.write(`${p.default.gray(_)}
|
|
56
|
+
`);let C=0,q=0;R(),s=setInterval(()=>{if(o&&a===f)return;g(),f=a;let ir=p.default.magenta(n[C]);if(o)process.stdout.write(`${ir} ${a}...`);else if(r==="timer")process.stdout.write(`${ir} ${a} ${nr(d)}`);else{let Bt=".".repeat(Math.floor(q)).slice(0,3);process.stdout.write(`${ir} ${a}${Bt}`)}C=C+1<n.length?C+1:0,q=q<n.length?q+0.125:0},t)},gr=(O="",C=0)=>{i=!1,clearInterval(s),g();let q=C===0?p.default.green(nn):C===1?p.default.red(Vn):p.default.red(Kn);a=N(O??a),r==="timer"?process.stdout.write(`${q} ${a} ${nr(d)}
|
|
57
|
+
`):process.stdout.write(`${q} ${a}
|
|
58
|
+
`),h(),e()};return{start:tr,stop:gr,message:(O="")=>{a=N(O??a)}}},Jn=async(r,n)=>{let t={},o=Object.keys(r);for(let e of o){let s=r[e],i=await s({results:t})?.catch((a)=>{throw a});if(typeof n?.onCancel=="function"&&A(i)){t[e]="canceled",n.onCancel({results:t});continue}t[e]=i}return t};var as=k({prefix:"cli-core"}).child("error");var ds=new Uint32Array(65536);var Yn=k({prefix:"cli-core"}).child("graceful");async function er(r,n={}){let{fallback:t,logLevel:o="warn",message:e="Operation failed gracefully"}=n;try{return await r()}catch(s){let i=s instanceof Error?s.message:String(s);if(Yn[o](`${e}: ${i}`),t)try{await t()}catch(a){Yn.error(`Fallback also failed: ${a instanceof Error?a.message:String(a)}`)}return}}function Xn(r){let n=[];if(n.push(y.bold(`${r.name} - ${r.description}`)),n.push(""),n.push(y.bold("USAGE")),n.push(` ${r.usage}`),n.push(""),r.options&&r.options.length>0){n.push(y.bold("OPTIONS"));for(let t of r.options){let o=t.type?t.type==="boolean"?y.boolean("[boolean]"):t.type==="string"?y.string("[string]"):t.type==="number"?y.number("[number]"):`[${t.type}]`:"",e=t.default!==void 0?y.dim(`(default: ${t.default})`):"",s=t.required?y.error("(required)"):"",i=[t.description,o,e,s].filter(Boolean);n.push(` ${y.flag(t.flags.padEnd(26))} ${i.join(" ")}`)}n.push("")}if(r.examples&&r.examples.length>0){n.push(y.bold("EXAMPLES"));for(let t of r.examples)n.push(y.dim(` # ${t.description}`)),n.push(` ${y.value(t.command)}`),n.push("")}if(r.sections&&r.sections.length>0)for(let t of r.sections){if(n.push(y.bold(t.title)),typeof t.content==="string")n.push(t.content);else n.push(...t.content);n.push("")}if(r.notes&&r.notes.length>0){n.push(y.bold("NOTES"));for(let t of r.notes)n.push(` - ${t}`);n.push("")}if(n[n.length-1]==="")n.pop();return n.join(`
|
|
59
|
+
`)}function Qn(r,n,t,o){let e=[];e.push(y.bold(r)),e.push(""),e.push(y.bold("USAGE")),e.push(` ${n}`),e.push(""),e.push(y.bold("COMMANDS"));let s=Math.max(...t.map((i)=>i.name.length));for(let i of t)e.push(` ${y.command(i.name.padEnd(s+2))} ${i.description}`);if(o)e.push(""),e.push(o);return e.join(`
|
|
60
|
+
`)}var Pi={backoffMultiplier:2,initialDelay:1000,maxAttempts:3,maxDelay:30000,onRetry:(r,n)=>{Ur.warn(`Retry attempt ${r}: ${n.message}`)},retryableErrors:["ECONNREFUSED","ECONNRESET","ETIMEDOUT","ENOTFOUND","rate limit","429","503","502","504","npm ERR!","EPUBLISHCONFLICT"]};async function vr(r,n={}){let t={...Pi,...n},o=new Error("Operation failed");for(let e=1;e<=t.maxAttempts;e++)try{return await r()}catch(s){if(o=s instanceof Error?s:new Error(String(s)),!t.retryableErrors.some((f)=>o.message.toLowerCase().includes(f.toLowerCase()))||e===t.maxAttempts)throw o;t.onRetry(e,o);let a=Math.min(t.initialDelay*t.backoffMultiplier**(e-1),t.maxDelay);await new Promise((f)=>setTimeout(f,a))}throw o}import{homedir as Li}from"os";import{join as Fn}from"path";var qi=Fn(Li(),".r5n","cache"),vs=Fn(qi,"update-check.json");var B=(r)=>{return r.map=(n)=>B((t)=>n(r(t))),r.or=(n)=>B((t)=>{try{return r(t)}catch(o){return n(t)}}),r},Tr=()=>"bad banditype"();var Dn=(r)=>B((n)=>r.includes(n)?n:Tr()),Nr=(r)=>B((n)=>typeof n===typeof r?n:Tr()),pr=()=>Nr(""),rt=()=>Nr(0),nt=()=>Nr(!0);var tt=()=>Nr();var it=(r)=>B((n)=>n instanceof r?n:Tr()),en=(r)=>it(Object).map((n)=>{let t={};for(let o in n){let e=r(n[o]);e!==void 0&&(t[o]=e)}return t}),sr=(r)=>it(Object).map((n)=>{let t={};for(let o in r){let e=r[o](n[o]);e!==void 0&&(t[o]=e)}return t});function Bi(r,n){return B((t)=>{try{return r(t)}catch{try{return n(t)}catch{throw new Error("No matching schema in union")}}})}function Q(r,n){return(t)=>{if(t===void 0)return n;return r(t)}}function ot(){return B((r)=>{let n=rt()(r);if(!Number.isInteger(n)||n<=0)throw new Error("Must be a positive integer");return n})}function et(){return B((r)=>{let n=pr()(r);try{return new URL(n),n}catch{throw new Error("Must be a valid URL")}})}function st(r,n){return B((t)=>{let o=pr()(t);if(!r.test(o))throw new Error(n||`Must match pattern ${r}`);return o})}function lr(r){return{parse(n){try{return r(n)}catch(t){throw new Error(t instanceof Error?t.message:"Validation failed")}},safeParse(n){try{return{data:r(n),success:!0}}catch(t){return{error:t instanceof Error?t:new Error("Validation failed"),success:!1}}},validator:r}}function Z(){return Bi(tt(),pr())}function F(r){return Q(pr(),r)}function ar(r){return Q(nt(),r)}function Ir(r,n){return Q(Dn(r),n)}function Ar(){let r=import.meta.path,n=r.substring(0,r.lastIndexOf("/"));return n.substring(0,n.lastIndexOf("/"))}var ji=sr({directory:F(`${process.cwd()}/gh-runners`),labels:Z(),name:F("runner"),numberOfMachines:Q(st(/^\d+$/,"Number of machines must be a positive integer"),"1"),os:Ir(["osx","linux","windows"],"osx"),overwrite:ar(!1),run:ar(!1),token:F(process.env.GITHUB_PERSONAL_ACCESS_TOKEN??""),url:et()}),Ys=lr(ji);function M(r){return r.replace(/[^a-zA-Z0-9\-_./\s]/g,"")}function at(r,n){let t=r;for(let o of n)if(o&&o.length>0){let e=o.length>8?`${o.slice(0,2)}${"*".repeat(o.length-4)}${o.slice(-2)}`:"*".repeat(o.length),s=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");t=t.replace(new RegExp(s,"g"),e)}return t=t.replace(/ghp_[a-zA-Z0-9]{36}/g,"ghp_************************************"),t=t.replace(/github_pat_[a-zA-Z0-9_]{82}/g,"github_pat_**********************************"),t=t.replace(/\b[A-Z]{20,}\b/g,(o)=>{return`${o.slice(0,2)}${"*".repeat(o.length-4)}${o.slice(-2)}`}),t}function x({prefix:r,secrets:n=[]}){let t=k({prefix:r}),o=[...n];if(process.env.GITHUB_TOKEN)o.push(process.env.GITHUB_TOKEN);if(process.env.RUNNER_TOKEN)o.push(process.env.RUNNER_TOKEN);if(process.env.RUNNER_CFG_PAT)o.push(process.env.RUNNER_CFG_PAT);let e=(s)=>{if(typeof s==="string")return at(s,o);if(typeof s==="object"&&s!==null){let i=Array.isArray(s)?[]:{};for(let a in s)i[a]=e(s[a]);return i}return s};return{...t,addSecret:(s)=>{if(s&&!o.includes(s))o.push(s)},child:(s)=>x({prefix:`${r}:${s}`,secrets:o}),debug:(...s)=>t.debug(...s.map(e)),error:(...s)=>t.error(...s.map(e)),info:(...s)=>t.info(...s.map(e)),warn:(...s)=>t.warn(...s.map(e))}}class Hr{thresholds;metrics={};startTimes=new Map;logger=x({prefix:"Performance"});defaultThresholds={startupTime:100,workerSpawnTime:50,memoryUsage:104857600,commandExecutionTime:5000};constructor(r={}){this.thresholds=r;this.thresholds={...this.defaultThresholds,...r}}startTimer(r){this.startTimes.set(r,fr.now())}endTimer(r){let n=this.startTimes.get(r);if(!n)throw new Error(`Timer ${r} was not started`);let t=fr.now()-n;return this.startTimes.delete(r),t}measureStartupTime(){let r=fr.now()-process.uptime()*1000;return this.metrics.startupTime=r,this.logger.debug(`Startup time: ${r.toFixed(2)}ms`),r}measureWorkerSpawn(r){return new Promise((n)=>{let t=fr.now();setTimeout(()=>{let e=fr.now()-t;if(!this.metrics.workerSpawnTimes)this.metrics.workerSpawnTimes=[];this.metrics.workerSpawnTimes.push(e),this.logger.debug(`Worker ${r} spawn time: ${e.toFixed(2)}ms`),n(e)},0)})}measureMemoryUsage(){let r=process.memoryUsage();this.metrics.memoryUsage=r;let n=(r.heapUsed/1024/1024).toFixed(2),t=(r.rss/1024/1024).toFixed(2);return this.logger.debug(`Memory usage - Heap: ${n}MB, RSS: ${t}MB`),r}async measureCommandExecution(r,n){this.startTimer(`command_${r}`);try{let t=await n(),o=this.endTimer(`command_${r}`);return this.metrics.commandExecutionTime=o,this.logger.debug(`Command ${r} execution time: ${o.toFixed(2)}ms`),{result:t,executionTime:o}}catch(t){throw this.endTimer(`command_${r}`),t}}getMetrics(){return{startupTime:this.metrics.startupTime||0,workerSpawnTimes:this.metrics.workerSpawnTimes||[],memoryUsage:this.metrics.memoryUsage||process.memoryUsage(),commandExecutionTime:this.metrics.commandExecutionTime||0,timestamp:Date.now()}}generateReport(){let r=this.getMetrics(),n=[];if(n.push({name:"Startup Time",value:r.startupTime,threshold:this.thresholds.startupTime,passed:r.startupTime<=this.thresholds.startupTime,unit:"ms"}),r.workerSpawnTimes.length>0){let s=r.workerSpawnTimes.reduce((a,f)=>a+f,0)/r.workerSpawnTimes.length,i=Math.max(...r.workerSpawnTimes);n.push({name:"Average Worker Spawn Time",value:s,threshold:this.thresholds.workerSpawnTime,passed:s<=this.thresholds.workerSpawnTime,unit:"ms"}),n.push({name:"Max Worker Spawn Time",value:i,threshold:this.thresholds.workerSpawnTime*2,passed:i<=this.thresholds.workerSpawnTime*2,unit:"ms"})}if(n.push({name:"Memory Usage (Heap Used)",value:r.memoryUsage.heapUsed,threshold:this.thresholds.memoryUsage,passed:r.memoryUsage.heapUsed<=this.thresholds.memoryUsage,unit:"bytes"}),n.push({name:"Memory Usage (RSS)",value:r.memoryUsage.rss,threshold:this.thresholds.memoryUsage*1.5,passed:r.memoryUsage.rss<=this.thresholds.memoryUsage*1.5,unit:"bytes"}),r.commandExecutionTime>0)n.push({name:"Command Execution Time",value:r.commandExecutionTime,threshold:this.thresholds.commandExecutionTime,passed:r.commandExecutionTime<=this.thresholds.commandExecutionTime,unit:"ms"});let t=n.filter((s)=>s.passed).length,o=n.length,e=Math.round(t/o*100);return{timestamp:r.timestamp,duration:fr.now(),results:n,summary:{passed:t,failed:o-t,total:o,score:e}}}logReport(r){this.logger.info("=== Performance Report ==="),this.logger.info(`Timestamp: ${new Date(r.timestamp).toISOString()}`),this.logger.info(`Duration: ${r.duration.toFixed(2)}ms`),this.logger.info(`Score: ${r.summary.score}% (${r.summary.passed}/${r.summary.total} passed)`),this.logger.info(`
|
|
61
|
+
Results:`);for(let n of r.results){let t=n.passed?"\u2705 PASS":"\u274C FAIL",o=n.unit==="bytes"?`${(n.value/1024/1024).toFixed(2)}MB`:`${n.value.toFixed(2)}${n.unit}`,e=n.unit==="bytes"?`${(n.threshold/1024/1024).toFixed(2)}MB`:`${n.threshold.toFixed(2)}${n.unit}`;this.logger.info(` ${t} ${n.name}: ${o} (threshold: ${e})`)}}reset(){this.metrics={},this.startTimes.clear()}}function sn(r){if(r===0)return"0 B";let n=["B","KB","MB","GB"],t=Math.floor(Math.log(r)/Math.log(1024));return`${(r/Math.pow(1024,t)).toFixed(2)} ${n[t]}`}function Sr(r){if(r<1000)return`${r.toFixed(2)}ms`;let n=r/1000;if(n<60)return`${n.toFixed(2)}s`;return`${(n/60).toFixed(2)}m`}var ta=new Hr;import{EventEmitter as Zi}from"events";import{performance as ct}from"perf_hooks";var Vi=sr({directory:F("./gh-runners"),labels:Z(),name:F("runner"),numberOfMachines:Q(ot(),1),os:Ir(["osx","linux","windows"],"osx"),overwrite:ar(!1),run:ar(!1),runnerGroup:Z(),token:Z(),url:Z()}),Ki=lr(Vi),ft=lr(sr({defaultProfile:Z(),profiles:en(Ki.validator)})),yr;((c)=>{c.INIT="init";c.START="start";c.STOP="stop";c.SHUTDOWN="shutdown";c.SUCCESS="success";c.ERROR="error";c.PROGRESS="progress";c.STATUS="status";c.HEARTBEAT="heartbeat";c.LOG="log"})(yr||={});function Cr(r){if(!r||typeof r!=="object"||r===null)return!1;let n=r;return typeof n.type==="string"&&Object.values(yr).includes(n.type)}function dt(r){if(!r||typeof r!=="object"||r===null)return!1;let n=r;return typeof n.machineCwd==="string"&&typeof n.token==="string"&&typeof n.url==="string"&&typeof n.index==="number"&&(n.name===void 0||typeof n.name==="string")&&(n.labels===void 0||typeof n.labels==="string")&&(n.runnerGroup===void 0||typeof n.runnerGroup==="string")}class D extends Zi{options;workers=new Map;workerInfo=new Map;shutdownInProgress=!1;logger=x({prefix:"WorkerManager"});cleanupRegistered=!1;constructor(r={}){super();this.options=r;this.options={gracefulShutdownTimeout:30000,maxRestarts:3,restartDelay:1000,restartOnError:!0,...r},this.registerCleanup()}registerCleanup(){if(this.cleanupRegistered)return;this.cleanupRegistered=!0;let r=async()=>{if(!this.shutdownInProgress)await this.shutdown()};process.on("exit",()=>{if(!this.shutdownInProgress&&this.workers.size>0)this.logger.warn("Forced exit with active workers")}),process.on("SIGINT",async()=>{this.logger.info("Received SIGINT, initiating graceful shutdown..."),await r(),process.exit(0)}),process.on("SIGTERM",async()=>{this.logger.info("Received SIGTERM, initiating graceful shutdown..."),await r(),process.exit(0)}),process.on("uncaughtException",async(n)=>{this.logger.error("Uncaught exception:",n),await r(),process.exit(1)})}async createWorker(r){if(this.shutdownInProgress)throw new Error("Cannot create worker during shutdown");if(this.workers.size>=(this.options.maxWorkers||100))throw new Error(`Maximum worker limit reached: ${this.options.maxWorkers}`);if(this.workers.has(r.id))throw new Error(`Worker with id ${r.id} already exists`);let n=ct.now(),t={id:r.id,name:r.name,restartCount:0,startTime:new Date,status:"starting"};this.workerInfo.set(r.id,t);try{let o=new Worker(r.scriptPath,{name:r.name,ref:!0});this.workers.set(r.id,o);let e=ct.now()-n;if(t.spawnTime=e,this.setupWorkerHandlers(o,r,t),r.data){let s={type:"init",data:r.data,timestamp:Date.now()};o.postMessage(s)}t.status="running",this.emit("workerStarted",t),this.emit("workerSpawned",{workerId:r.id,spawnTime:e}),this.logger.info(`Worker ${r.name} (${r.id}) started in ${e.toFixed(2)}ms`)}catch(o){throw t.status="error",t.error=o,t.endTime=new Date,this.emit("workerError",t,o),o}}setupWorkerHandlers(r,n,t){r.addEventListener("message",({data:o})=>{if(Cr(o))this.emit("workerMessage",t,o),n.onMessage?.(o);else this.logger.warn(`Received invalid message from worker ${n.name}:`,o)}),r.addEventListener("error",(o)=>{if(this.logger.error(`Worker ${n.name} error:`,o),t.status="error",t.error=o.error||o,this.emit("workerError",t,o),n.onError?.(o.error||o),this.options.restartOnError&&t.restartCount<(this.options.maxRestarts||3))this.scheduleRestart(n,t)}),r.addEventListener("messageerror",(o)=>{this.logger.error(`Worker ${n.name} message error:`,o),t.status="error",t.error=new Error("Worker message error"),this.emit("workerError",t,o),n.onError?.(new Error("Worker message error"))})}scheduleRestart(r,n){let t=this.options.restartDelay||1000;n.restartCount++,this.logger.info(`Scheduling restart for worker ${r.name} (attempt ${n.restartCount}/${this.options.maxRestarts}) in ${t}ms`),setTimeout(async()=>{if(!this.shutdownInProgress)try{await this.createWorker(r)}catch(o){this.logger.error(`Failed to restart worker ${r.name}:`,o)}},t)}async stopWorker(r,n=!1){let t=this.workers.get(r),o=this.workerInfo.get(r);if(!t||!o)throw new Error(`Worker ${r} not found`);if(o.status="stopping",this.emit("workerStopping",o),n)t.terminate(),this.workers.delete(r),o.status="stopped",o.endTime=new Date,this.emit("workerStopped",o);else{let e={type:"shutdown",data:{graceful:!0},timestamp:Date.now()};t.postMessage(e),await new Promise((s)=>{let i=setTimeout(()=>{this.logger.warn(`Worker ${o.name} did not stop gracefully, terminating...`),t.terminate(),s()},this.options.gracefulShutdownTimeout||30000);t.addEventListener("exit",()=>{clearTimeout(i),s()})})}}async shutdown(){if(this.shutdownInProgress)return;this.shutdownInProgress=!0,this.logger.info(`Shutting down ${this.workers.size} workers...`);let r=Array.from(this.workers.keys()).map((n)=>this.stopWorker(n).catch((t)=>{this.logger.error(`Error stopping worker ${n}:`,t)}));await Promise.all(r),this.workers.clear(),this.workerInfo.clear(),this.logger.info("All workers shut down")}getWorkerInfo(r){return this.workerInfo.get(r)}getAllWorkerInfo(){return Array.from(this.workerInfo.values())}getWorkerCount(){return this.workers.size}isShuttingDown(){return this.shutdownInProgress}}import{join as Ji}from"path";import{fileURLToPath as Yi}from"url";import{dirname as Xi}from"path";var Qi=Yi(import.meta.url),Fi=Xi(Qi),S=x({prefix:"Benchmark"});async function mt(){let{values:r}=zi({args:process.argv.slice(2),options:{help:{type:"boolean",short:"h"},iterations:{type:"string",default:"3"},workers:{type:"string",default:"3"},"startup-only":{type:"boolean"},"memory-only":{type:"boolean"},"worker-only":{type:"boolean"},quick:{type:"boolean"}},allowPositionals:!0});if(r.help){console.log(`
|
|
62
|
+
Usage: hydra benchmark [options]
|
|
63
|
+
|
|
64
|
+
Options:
|
|
65
|
+
--iterations=N Number of benchmark iterations (default: 3)
|
|
66
|
+
--workers=N Number of workers to test (default: 3)
|
|
67
|
+
--startup-only Test only CLI startup time
|
|
68
|
+
--memory-only Test only memory usage
|
|
69
|
+
--worker-only Test only worker spawn performance
|
|
70
|
+
--quick Run a quick benchmark (1 iteration)
|
|
71
|
+
--help, -h Show this help message
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
hydra benchmark
|
|
75
|
+
hydra benchmark --iterations=5 --workers=10
|
|
76
|
+
hydra benchmark --quick
|
|
77
|
+
hydra benchmark --startup-only
|
|
78
|
+
`);return}let n=r.quick?1:parseInt(r.iterations),t=parseInt(r.workers),o=new Hr({startupTime:100,workerSpawnTime:50,memoryUsage:104857600,commandExecutionTime:1000});S.info("Starting Hydra CLI Performance Benchmark...");try{if(r["startup-only"])await ut(o,n);else if(r["memory-only"])await pt(o);else if(r["worker-only"])await lt(o,t);else await Di(o,n,t);let e=o.generateReport();if(o.logReport(e),e.summary.score<70)S.warn("Performance score is below acceptable threshold (70%)"),process.exit(1);else if(e.summary.score>=95)S.info("Excellent performance! \uD83D\uDE80");else if(e.summary.score>=85)S.info("Good performance! \uD83D\uDC4D")}catch(e){S.error("Benchmark failed:",e),process.exit(1)}}async function ut(r,n){S.info(`Running startup benchmark (${n} iterations)...`);let t=0;for(let e=0;e<n;e++)if(r.startTimer("startup"),await new Promise((s)=>{setTimeout(()=>{let i=r.endTimer("startup");t+=i,s(i)},10)}),e<n-1)await new Promise((s)=>setTimeout(s,50));let o=t/n;r.getMetrics().startupTime=o,S.info(`Average startup time: ${Sr(o)}`)}async function pt(r){S.info("Running memory usage benchmark..."),global.gc?.(),await new Promise((t)=>setTimeout(t,100));let n=r.measureMemoryUsage();S.info(`Heap used: ${sn(n.heapUsed)}`),S.info(`RSS memory: ${sn(n.rss)}`)}async function lt(r,n){S.info(`Running worker spawn benchmark (${n} workers)...`);let t=new D,o=[];t.on("workerSpawned",({spawnTime:e})=>{o.push(e)});try{let e=[];for(let a=0;a<n;a++){let f=t.createWorker({id:`benchmark-worker-${a}`,name:`BenchmarkWorker${a}`,scriptPath:Ji(Fi,"../runner-worker.ts"),data:{machineCwd:process.cwd(),token:"benchmark-token",url:"https://github.com/test/repo",index:a}});e.push(f),await new Promise((d)=>setTimeout(d,10))}await Promise.all(e),r.getMetrics().workerSpawnTimes=o;let s=o.reduce((a,f)=>a+f,0)/o.length,i=Math.max(...o);S.info(`Average worker spawn time: ${Sr(s)}`),S.info(`Max worker spawn time: ${Sr(i)}`)}finally{await t.shutdown()}}async function Di(r,n,t){S.info(`Running full benchmark suite (${n} iterations, ${t} workers)...`),await ut(r,Math.min(n,3)),await new Promise((o)=>setTimeout(o,100)),await pt(r),await new Promise((o)=>setTimeout(o,100)),await lt(r,Math.min(t,3)),S.info("Full benchmark suite completed")}import{homedir as ao}from"os";import{join as fo}from"path";import{parseArgs as co}from"util";var{$:xt}=globalThis.Bun;import{join as ro}from"path";var{$:j}=globalThis.Bun;class yt{async exists(r){return Bun.file(r).exists()}async readFile(r){let n=Bun.file(r);if(!await n.exists())throw new Error(`File not found: ${r}`);return n.text()}async writeFile(r,n){await Bun.write(r,n)}async deleteFile(r){let n=M(r);await j`rm -f ${n}`.quiet()}async createDirectory(r,n){let t=M(r);if(n?.recursive)await j`mkdir -p ${t}`.quiet();else await j`mkdir ${t}`.quiet()}async deleteDirectory(r,n){let t=M(r);if(n?.recursive)await j`rm -rf ${t}`.quiet();else await j`rmdir ${t}`.quiet()}async listDirectory(r){let n=M(r),o=(await j`ls -la ${n}`.quiet()).stdout.toString().trim().split(`
|
|
79
|
+
`),e=[];for(let s of o.slice(1)){let i=s.split(/\s+/);if(i.length<9)continue;let a=i[0],f=Number.parseInt(i[4]||"0",10),d=i.slice(8).join(" ");if(d==="."||d==="..")continue;e.push({isDirectory:a?.startsWith("d")||!1,modifiedTime:new Date,name:d,size:f})}return e}async copyFile(r,n){let t=M(r),o=M(n);await j`cp ${t} ${o}`.quiet()}async moveFile(r,n){let t=M(r),o=M(n);await j`mv ${t} ${o}`.quiet()}async getFileInfo(r){if(!await Bun.file(r).exists())return null;let t=M(r),e=(await j`stat -f "%z %m %Y" ${t} 2>/dev/null || stat -c "%s %Y %F" ${t}`.quiet()).stdout.toString().trim().split(" "),s=e[0]||"0",i=e[1]||"0";return{isDirectory:!1,modifiedTime:new Date(Number.parseInt(i,10)*1000),name:r.split("/").pop()||r,size:Number.parseInt(s,10)}}async chmod(r,n){let t=M(r);await j`chmod ${n} ${t}`.quiet()}async readDir(r){return(await this.listDirectory(r)).map((t)=>({isDirectory:t.isDirectory,isFile:!t.isDirectory,name:t.name}))}async ensureDir(r){if(!await this.exists(r))await this.createDirectory(r,{recursive:!0})}}var b=new yt;async function an(r){if(!await b.exists(r))await b.createDirectory(r,{recursive:!0})}var no=["hydra.json",".hydra.json","hydra.toml",".hydra.toml"];async function fn(r=process.cwd()){for(let n of no){let t=ro(r,n);if(await b.exists(t))return t}return null}async function G(r){let n=r?.configPath||await fn();if(!n)return null;if(!await b.exists(n))return null;try{let t=await b.readFile(n),o=n.endsWith(".toml")?to(t):JSON.parse(t);return ft.parse(o)}catch(t){if(t instanceof Error)throw new Error(`Invalid config file: ${t.message}`);throw t}}async function U(r,n){if(!r)return null;let t=n||r.defaultProfile;if(!t)return null;return r.profiles[t]||null}function ht(r,n){if(!r)return n;let t={...n};for(let[o,e]of Object.entries(r)){let s=o;if(t[s]===void 0&&e!==void 0)t[s]=e}return t}function to(r){try{return Bun.TOML.parse(r)}catch(n){throw new Error(`Failed to parse TOML configuration: ${n}`)}}var Rt=k({prefix:"runner-templates"}),dn={postHook:`git reset --hard && git clean --force -df
|
|
80
|
+
`,preHook:`export BUN_INSTALL_CACHE_DIR=./.bun/cache
|
|
81
|
+
`,runnerEnv:`ACTIONS_RUNNER_HOOK_JOB_STARTED=./hooks/pre.sh
|
|
82
|
+
ACTIONS_RUNNER_HOOK_JOB_COMPLETED=./hooks/post.sh
|
|
83
|
+
`};async function gt(r){try{let n=`${r}/hooks`;await Bun.$`mkdir -p ${n}`.quiet(),await Bun.write(`${n}/pre.sh`,dn.preHook),await Bun.$`chmod +x ${n}/pre.sh`.quiet(),await Bun.write(`${n}/post.sh`,dn.postHook),await Bun.$`chmod +x ${n}/post.sh`.quiet(),await Bun.write(`${r}/.runner-env`,dn.runnerEnv),Rt.debug(`Created runner hooks and environment for ${r}`)}catch(n){throw Rt.error("Failed to create runner files:",n),n}}var Sa=k({prefix:"worker-validator"});class wt{validateWorkerData(r){let n={errors:[],valid:!0,warnings:[]};if(!dt(r))return n.valid=!1,n.errors.push({code:"INVALID_WORKER_DATA",field:"data",message:"Invalid worker data format"}),n;let t=r;if(this.validateUrl(t.url,n),this.validateToken(t.token,n),t.index<0)n.valid=!1,n.errors.push({code:"INVALID_INDEX",field:"index",message:"Worker index must be non-negative"});return n}validateWorkerMessage(r){let n={errors:[],valid:!0,warnings:[]};if(!Cr(r))return n.valid=!1,n.errors.push({code:"INVALID_WORKER_MESSAGE",field:"message",message:"Invalid worker message format"}),n;if(!Object.values(yr).includes(r.type))n.valid=!1,n.errors.push({code:"INVALID_MESSAGE_TYPE",field:"type",message:`Invalid message type: ${r.type}`});return n}validateGitHubRelease(r){let n={errors:[],valid:!0,warnings:[]};if(!r||typeof r!=="object")return n.valid=!1,n.errors.push({code:"INVALID_GITHUB_RELEASE",field:"release",message:"GitHub release must be an object"}),n;let t=r;if(this.validateRequiredString(t.tag_name,"tag_name",n),this.validateRequiredString(t.html_url,"html_url",n),this.validateRequiredNumber(t.id,"id",n),t.draft!==void 0&&typeof t.draft!=="boolean")n.valid=!1,n.errors.push({code:"INVALID_TYPE",field:"draft",message:"Draft field must be a boolean"});if(t.prerelease!==void 0&&typeof t.prerelease!=="boolean")n.valid=!1,n.errors.push({code:"INVALID_TYPE",field:"prerelease",message:"Prerelease field must be a boolean"});if(t.prerelease===!0)n.warnings.push({code:"PRERELEASE_VERSION",field:"prerelease",message:"This is a prerelease version which may be unstable"});if(t.assets&&Array.isArray(t.assets))for(let[o,e]of t.assets.entries())this.validateGitHubReleaseAsset(e,`assets[${o}]`,n);return n}validateRequiredString(r,n,t){if(!r||typeof r!=="string")t.valid=!1,t.errors.push({code:"MISSING_REQUIRED_FIELD",field:n,message:`${n} is required and must be a string`});else if(r.trim().length===0)t.valid=!1,t.errors.push({code:"EMPTY_REQUIRED_FIELD",field:n,message:`${n} cannot be empty`})}validateRequiredNumber(r,n,t){if(typeof r!=="number")t.valid=!1,t.errors.push({code:"MISSING_REQUIRED_FIELD",field:n,message:`${n} is required and must be a number`});else if(!Number.isInteger(r))t.valid=!1,t.errors.push({code:"INVALID_NUMBER",field:n,message:`${n} must be an integer`});else if(r<0)t.valid=!1,t.errors.push({code:"NEGATIVE_NUMBER",field:n,message:`${n} must be a non-negative number`})}validateGitHubReleaseAsset(r,n,t){if(!r||typeof r!=="object"){t.valid=!1,t.errors.push({code:"INVALID_RELEASE_ASSET",field:n,message:"Release asset must be an object"});return}let o=r;if(!o.name||typeof o.name!=="string")t.valid=!1,t.errors.push({code:"MISSING_ASSET_NAME",field:`${n}.name`,message:"Asset name is required"});if(!o.browser_download_url||typeof o.browser_download_url!=="string")t.valid=!1,t.errors.push({code:"MISSING_DOWNLOAD_URL",field:`${n}.browser_download_url`,message:"Asset download URL is required"})}validateUrl(r,n){try{let t=new URL(r);if(!t.hostname.includes("github.com")&&!t.hostname.includes("github"))n.warnings.push({code:"NON_GITHUB_URL",field:"url",message:"URL does not appear to be a GitHub URL"})}catch{n.valid=!1,n.errors.push({code:"INVALID_URL",field:"url",message:"Invalid URL format"})}}validateToken(r,n){if(r.length<10)n.warnings.push({code:"SHORT_TOKEN",field:"token",message:"Token appears to be too short"});if(r.includes(" "))n.valid=!1,n.errors.push({code:"INVALID_TOKEN_FORMAT",field:"token",message:"Token cannot contain spaces"})}}function oo(){return new wt}function bt(r){return oo().validateGitHubRelease(r)}function eo(r){if(!r||typeof r!=="object")return!1;let n=r;if(typeof n.name!=="string"||n.name.trim().length===0)return!1;if(n.description!==void 0&&typeof n.description!=="string")return!1;if(n.extends!==void 0&&typeof n.extends!=="string")return!1;if(n.metadata!==void 0){if(typeof n.metadata!=="object"||n.metadata===null)return!1;let t=n.metadata;if(t.author!==void 0&&typeof t.author!=="string"||t.created!==void 0&&typeof t.created!=="string"||t.updated!==void 0&&typeof t.updated!=="string"||t.tags!==void 0&&(!Array.isArray(t.tags)||!t.tags.every((o)=>typeof o==="string")))return!1}return!0}function so(r){if(!r||typeof r!=="object")return!1;let n=r;if(!n.templates||typeof n.templates!=="object"||n.templates===null)return!1;let t=n.templates;for(let[o,e]of Object.entries(t))if(typeof o!=="string"||!eo(e))return!1;if(n.version!==void 0&&typeof n.version!=="string")return!1;return!0}function cn(r){if(!so(r))throw new Error("Invalid template store: must contain a valid templates object")}async function Et(r,n={}){let{maxAttempts:t=5,baseDelay:o=1000,onRetry:e}=n;for(let s=1;s<=t;s++)try{return await r()}catch(i){if(s===t)throw i;let a=Math.min(o*Math.pow(2,s-1),16000),f=Math.random()*0.1*a,d=a+f;if(e)e(s,i instanceof Error?i:new Error(String(i)));await new Promise((c)=>setTimeout(c,d))}throw new Error("Retry logic should not reach here")}async function $t(){let r=x({prefix:"createMachines"}),n=await uo(),{overwrite:t,directory:o,numberOfMachines:e,os:s,run:i,name:a,labels:f,runnerGroup:d}=n,{token:c,url:u}=n;if(!u)throw w.createError("URL (-u) parameter is required","VALIDATION_ERROR",void 0,{operation:"create_machines",parameter:"url"});if(!c){let R=mo(u),h=await H({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
84
|
+
${R}`});if(A(h)||!h)throw w.createError("Token is required to create runners","AUTHENTICATION_ERROR",void 0,{operation:"create_machines",parameter:"token"});r.info("Opening GitHub runner settings..."),await xt`open ${R}`.quiet();let g=await T({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(N)=>{if(!N||N.trim().length===0)return"Token is required";return}});if(A(g))throw w.createError("Token is required to create runners","AUTHENTICATION_ERROR",void 0,{operation:"create_machines",parameter:"token"});c=g.trim()}if(r=x({prefix:"createMachines",secrets:[c]}),r.info(`Creating ${e} runners in ${o}`),r.debug(`OS: ${s}, Name: ${a}, Labels: ${f||"none"}`),await b.exists(o))if(t)r.warn(`Directory ${o} exists, removing...`),await b.deleteDirectory(o,{recursive:!0});else throw w.createError(`Directory ${o} already exists`,"FILE_SYSTEM_ERROR",void 0,{operation:"create_machines",directory:o});let l=await lo({directory:o,os:s});if(await yo({directory:o,numberOfMachines:e,overwrite:t,runnerBase:l}),!i){r.info("Runners created but not started");return}await ho({directory:o,labels:f,name:a,numberOfMachines:e,runnerGroup:d,token:c,url:u})}function mo(r){try{let n=new URL(r),t=n.pathname.split("/").filter(Boolean);if(n.hostname==="github.com"||n.hostname==="www.github.com"){if(t[0]==="orgs"&&t[1])return`https://github.com/organizations/${t[1]}/settings/actions/runners/new`;if(t.length>=2)return`https://github.com/${t[0]}/${t[1]}/settings/actions/runners/new`}else{if(t[0]==="orgs"&&t[1])return`${n.origin}/organizations/${t[1]}/settings/actions/runners/new`;if(t.length>=2)return`${n.origin}/${t[0]}/${t[1]}/settings/actions/runners/new`}return r}catch{return r}}async function uo(){let{values:r}=co({args:process.argv.slice(3),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}),n=await G({configPath:r.config}),t=await U(n,r.profile),o;if(r.template)o=await Ro(r.template);let e={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},s=t||o?{directory:e.directory??t?.directory??o?.directory??`${process.cwd()}/gh-runners`,labels:e.labels??t?.labels??o?.labels,name:e.name??t?.name??o?.name??"runner",numberOfMachines:e.numberOfMachines??String(t?.numberOfMachines??o?.numberOfMachines)??"1",os:e.os??t?.os??o?.os??"osx",overwrite:e.overwrite??t?.overwrite??o?.overwrite??!1,run:e.run??t?.run??o?.run??!1,runnerGroup:e.runnerGroup??t?.runnerGroup??o?.runnerGroup,token:e.token||t?.token,url:e.url??t?.url??o?.url}:null;if(s)return s;return{directory:e.directory,labels:e.labels,name:e.name,numberOfMachines:e.numberOfMachines,os:e.os,overwrite:e.overwrite,run:e.run,runnerGroup:e.runnerGroup,token:e.token,url:e.url}}async function po(r){let n=x({prefix:"github-release-validator",secrets:[]});try{let t=await fetch(r);if(!t.ok)throw w.createError(`GitHub API request failed: ${t.status} ${t.statusText}`,"GITHUB_API_ERROR",void 0,{operation:"validate_github_release",status:t.status});let o=await t.json(),e=bt(o);if(!e.valid){n.error("GitHub release validation failed:");for(let s of e.errors)n.error(` ${s.field}: ${s.message}`);throw w.createError("Invalid GitHub release response format","GITHUB_API_ERROR",void 0,{operation:"validate_github_release"})}if(e.warnings.length>0){n.warn("GitHub release validation warnings:");for(let s of e.warnings)n.warn(` ${s.field}: ${s.message}`)}n.debug("GitHub release validation passed")}catch(t){if(t instanceof Error)throw t;throw new Error(`GitHub release validation error: ${String(t)}`)}}async function lo({directory:r,os:n}){let t=x({prefix:"createMachines:download",secrets:[]});t.info(`Fetching latest runner version for ${n}...`);let o=await Et(async()=>{let f=await fetch("https://github.com/actions/runner/releases/latest",{method:"GET",redirect:"manual"});if(f.status>=300&&f.status<400){let d=f.headers.get("location");if(d)return d}throw new Error(`Failed to get redirect URL: ${f.status}`)},{onRetry:(f,d)=>{t.warn(`Retrying GitHub API call (attempt ${f}): ${d.message}`)}});if(!o||typeof o!=="string")throw w.createError("Invalid release info received from GitHub","GITHUB_API_ERROR",void 0,{operation:"get_latest_github_runner_release"});if(!o.includes("github.com/actions/runner/releases/tag/"))throw new Error(`Invalid GitHub release URL format: ${o}`);let e=o.split("/").pop()||"";if(!e)throw new Error("Could not extract release tag from GitHub URL");let s=e.trim().replace("v","");if(!s||s.length===0)throw new Error("Invalid version extracted from release tag");if(process.env.HYDRA_VALIDATE_GITHUB_RELEASES==="true"){t.debug("Performing additional GitHub release validation...");let f=`https://api.github.com/repos/actions/runner/releases/tags/${e}`;try{await po(f)}catch(d){t.warn(`GitHub release validation failed (non-critical): ${d instanceof Error?d.message:String(d)}`)}}let i=`actions-runner-${n}-x64-${s}.tar.gz`,a=`https://github.com/actions/runner/releases/download/v${s}/${i}`;if(t.debug(`Runner version: ${s}`),t.debug(`Download URL: ${a}`),await an(r),await an(`${r}/machines`),!await b.exists(`${r}/${i}`))t.info("Downloading runner image..."),await Et(async()=>{let f=await fetch(a);if(!f.ok)throw new Error(`Download failed: ${f.status} ${f.statusText}`);if(!f.body)throw new Error("No response body");let d=f.body.getReader(),c=[];try{while(!0){let{done:h,value:g}=await d.read();if(h)break;c.push(g)}}finally{d.releaseLock()}let u=c.reduce((h,g)=>h+g.length,0),l=new Uint8Array(u),R=0;for(let h of c)l.set(h,R),R+=h.length;await Bun.write(`${r}/${i}`,l)},{maxAttempts:5,onRetry:(f,d)=>{t.warn(`Retrying runner download (attempt ${f}): ${d.message}`)}}),t.info("Download complete");else t.info("Runner image already exists, skipping download");return i}async function yo({overwrite:r,numberOfMachines:n,directory:t,runnerBase:o}){let e=x({prefix:"createMachines:extract",secrets:[]}),s=Number(n),i=(()=>{try{let c=Bun.spawnSync(["nproc"]);return Number.parseInt(c.stdout.toString().trim(),10)||4}catch{try{let c=Bun.spawnSync(["sysctl","-n","hw.ncpu"]);return Number.parseInt(c.stdout.toString().trim(),10)||4}catch{return 4}}})(),a=Math.min(Math.max(2,Math.floor(i/2)),s,8);e.info(`Extracting ${s} runners with concurrency of ${a}`);let f=Array.from({length:s},(c,u)=>u+1).map((c)=>({execute:async()=>{let u=`${t}/machines/${c}`;if(await b.exists(u))if(r)e.debug(`Machine ${c} already exists, removing...`),await b.deleteDirectory(u,{recursive:!0});else{e.debug(`Machine ${c} already exists, skipping...`);return}await b.createDirectory(u),await xt`tar xzf ${o} -C ${u.replace(`${t}/`,"")}`.cwd(t),await gt(u),e.debug(`Machine ${c} extracted successfully`)},runnerIndex:c})),d=[];for(let c=0;c<f.length;c+=a){let u=f.slice(c,c+a),l=Math.floor(c/a)+1,R=Math.ceil(f.length/a);e.info(`Processing batch ${l}/${R} (${u.length} runners)`);let h=await Promise.allSettled(u.map((g)=>g.execute()));for(let g=0;g<h.length;g++){let N=h[g];if(N&&N.status==="rejected")throw e.error(`Failed to extract runner ${u[g]?.runnerIndex}: ${N.reason}`),N.reason}d.push(...h),e.info(`Batch ${l}/${R} completed successfully`)}e.info(`Successfully extracted ${s} runners`)}async function ho({directory:r,numberOfMachines:n,token:t,url:o,name:e,labels:s,runnerGroup:i}){let a=x({prefix:"createMachines:start",secrets:[t]});a.info(`Starting ${n} runners concurrently...`);let f=new D({maxRestarts:3,maxWorkers:Number(n),restartDelay:5000,restartOnError:!0}),d=Array.from({length:Number(n)},(h,g)=>{let N=g+1,nr=`${Ar()}/src/runner-worker.ts`,tr=`${e}-${N}`,gr=`runner-${N}`;return{data:{index:N,labels:s,machineCwd:`${r}/machines/${N}`,name:e,runnerGroup:i,token:t,url:o},id:gr,name:tr,onError:(O)=>{a.error(`Worker ${tr} error:`,O)},onExit:(O)=>{a.info(`Worker ${tr} exited with code ${O}`)},onMessage:(O)=>{let C=O.type==="error"?"error":"info";a[C](`${tr}: ${O.message}`)},scriptPath:nr}}),c=d.map(async(h)=>{try{return await f.createWorker(h),{success:!0,workerId:h.id,workerName:h.name}}catch(g){return a.error(`Failed to start worker ${h.name}:`,g),{success:!1,workerId:h.id,workerName:h.name,error:g}}}),u=await Promise.allSettled(c),l=0,R=0;if(u.forEach((h,g)=>{if(h.status==="fulfilled")if(h.value.success)l++,a.debug(`Worker ${h.value.workerName} started successfully`);else R++,a.error(`Worker ${h.value.workerName} failed to start: ${h.value.error}`);else{R++;let N=d[g];a.error(`Unexpected error starting worker ${N?.name}:`,h.reason)}}),R>0)a.warn(`${l} workers started successfully, ${R} failed`),a.info("Failed workers will be reported but won't stop other workers");else a.info(`All ${l} workers started successfully`);a.info("Press Ctrl+C to stop all machines")}async function Ro(r){let n=x({prefix:"loadTemplate"}),t="./hydra-templates.json",o=Bun.file("./hydra-templates.json");if(await o.exists())try{let i=await o.json();if(cn(i),i.templates?.[r])return n.info(`Using local template: ${r}`),mn(i.templates[r],i.templates)}catch(i){n.warn(`Failed to load local templates: ${i}`)}let e=fo(ao(),".hydra","templates.json"),s=Bun.file(e);if(await s.exists())try{let i=await s.json();if(cn(i),i.templates?.[r])return n.info(`Using global template: ${r}`),mn(i.templates[r],i.templates)}catch(i){n.warn(`Failed to load global templates: ${i}`)}n.warn(`Template '${r}' not found`);return}function mn(r,n,t=new Set){if(r.name&&t.has(r.name))throw w.createError(`Circular template dependency detected: ${r.name}`,"TEMPLATE_ERROR",void 0,{operation:"resolve_template_inheritance",templateName:r.name});if(r.name)t.add(r.name);let o={};if(r.extends&&n[r.extends]){let d=n[r.extends];if(d)o=mn(d,n,t)}let{name:e,description:s,extends:i,metadata:a,...f}=r;return{...o,...f}}import{existsSync as hr}from"fs";import{readdir as _t}from"fs/promises";import{join as z,resolve as go}from"path";import{parseArgs as wo}from"util";var{$:pn}=globalThis.Bun;var bo=k({prefix:"hydra"}).child("health");async function Eo(){let{values:r}=wo({args:process.argv.slice(3),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}),n=await G({configPath:r.config}),t=await U(n,r.profile);return{directory:r.directory||t?.directory||`${process.cwd()}/gh-runners`,fix:r.fix,json:r.json,runner:r.runner,token:r.token,url:r.url||t?.url}}async function Ot(){try{let r=await Eo(),n=go(r.directory),t=z(n,"machines");if(!hr(t)){m.error(`No runners found in ${r.directory}`);return}let o=K();o.start("Performing health checks...");let e=await _t(t),s=[];for(let i of e){if(r.runner&&i!==r.runner)continue;let a=z(t,i),f=await xo(i,a,r);s.push(f)}if(o.stop("Health checks completed"),r.json){console.log(JSON.stringify(s,null,2));return}if(ko(s),r.fix)await vo(s,r)}catch(r){bo.error("Failed to perform health checks:",r),process.exit(1)}}async function xo(r,n,t){let o=[],e={configuration:!1,connectivity:!1,disk:{percentage:0,total:0,used:0},lastActivity:null,process:!1};try{let i=z(n,".runner");if(hr(i)){let a=await Bun.file(i).text(),f=await $o(a.trim());if(e.process=f,!f)o.push("Runner process is not running")}else o.push("No PID file found")}catch{o.push("Could not check process status")}try{let i=await _o(n);if(e.disk=i,i.percentage>90)o.push(`Low disk space: ${i.percentage.toFixed(1)}% used`)}catch{o.push("Could not check disk space")}try{let i=z(n,"_diag");if(hr(i)){let a=await _t(i),f=null;for(let d of a)if(d.endsWith(".log")){let c=await Bun.file(z(i,d)).stat();if(!f||c.mtime>f)f=new Date(c.mtime)}if(e.lastActivity=f,f){let d=(Date.now()-f.getTime())/3600000;if(d>24)o.push(`No activity for ${Math.floor(d)} hours`)}}}catch{o.push("Could not check last activity")}try{let i=z(n,".runner"),a=z(n,".credentials");if(e.configuration=hr(i)&&hr(a),!e.configuration)o.push("Missing configuration files")}catch{o.push("Could not check configuration")}if(t.token&&t.url)try{let i=await Oo(t.url,t.token);if(e.connectivity=i,!i)o.push("Cannot connect to GitHub API")}catch{o.push("Failed to check GitHub connectivity")}let s="healthy";if(o.length===0)s="healthy";else if(o.some((i)=>i.includes("not running")||i.includes("Missing configuration")||i.includes("Cannot connect")))s="critical";else if(o.length>0)s="warning";return{checks:e,issues:o,runner:r,status:s}}async function $o(r){try{return await pn`kill -0 ${r}`.quiet(),!0}catch{return!1}}async function _o(r){let t=(await pn`df -k ${r} | tail -1`.text()).trim().split(/\s+/),o=Number.parseInt(t[1]||"0",10)*1024,e=Number.parseInt(t[2]||"0",10)*1024;return{percentage:Number.parseInt(t[4]?.replace("%","")||"0",10),total:o,used:e}}async function Oo(r,n){return vr(async()=>{let t=r.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!t)return!1;let[,o,e]=t,s=e?`https://api.github.com/repos/${o}/${e}`:`https://api.github.com/orgs/${o}`;return(await fetch(s,{headers:{Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${n}`}})).ok},{maxAttempts:3})}function ko(r){console.log(),console.log(y.bold("\uD83C\uDFE5 Runner Health Status")),console.log("\u2500".repeat(80));let n={critical:"\u274C",healthy:"\u2705",unknown:"\u2753",warning:"\u26A0\uFE0F"},t={critical:y.error,healthy:y.success,unknown:y.dim,warning:y.warning};for(let e of r){let s=n[e.status],i=t[e.status];if(console.log(`${s} ${y.bold(`Runner ${e.runner}`)}: ${i(e.status.toUpperCase())}`),console.log(` Process: ${e.checks.process?"\u2705 Running":"\u274C Not running"}`),console.log(` Config: ${e.checks.configuration?"\u2705 Valid":"\u274C Missing"}`),e.checks.disk.total>0){let a=e.checks.disk.percentage>90?y.error:y.success;console.log(` Disk: ${a(`${e.checks.disk.percentage.toFixed(1)}% used`)}`)}if(e.checks.lastActivity){let f=(Date.now()-e.checks.lastActivity.getTime())/3600000>24?y.warning:y.success;console.log(` Last Activity: ${f(To(e.checks.lastActivity))}`)}if(e.checks.connectivity!==null)console.log(` GitHub API: ${e.checks.connectivity?"\u2705 Connected":"\u274C Disconnected"}`);if(e.issues.length>0){console.log(" Issues:");for(let a of e.issues)console.log(` - ${y.dim(a)}`)}console.log()}let o={critical:r.filter((e)=>e.status==="critical").length,healthy:r.filter((e)=>e.status==="healthy").length,total:r.length,warning:r.filter((e)=>e.status==="warning").length};console.log("\u2500".repeat(80)),console.log(`Summary: Total: ${o.total} | ${y.success(`Healthy: ${o.healthy}`)} | ${y.warning(`Warning: ${o.warning}`)} | ${y.error(`Critical: ${o.critical}`)}`)}async function vo(r,n){let t=r.filter((e)=>e.status==="critical");if(t.length===0){m.info("No critical issues found that require fixing");return}if(console.log(),!await H({initialValue:!1,message:`Found ${t.length} runners with critical issues. Attempt to fix?`}))return;for(let e of t){if(console.log(),m.info(`Attempting to fix runner ${e.runner}...`),!e.checks.process&&e.checks.configuration){m.info("Attempting to restart runner...");try{let s=z(n.directory,"machines",e.runner);await pn`cd ${s} && ./run.sh`.quiet(),m.success(`Runner ${e.runner} restarted successfully`)}catch(s){m.error(`Failed to restart runner ${e.runner}`)}}if(!e.checks.configuration)m.warning(`Runner ${e.runner} needs to be reconfigured. Run 'hydra create' to set up again.`)}}function To(r){let t=new Date().getTime()-r.getTime(),o=Math.floor(t/3600000);if(o<1)return`${Math.floor(t/60000)}m ago`;if(o<24)return`${o}h ago`;return`${Math.floor(o/24)}d ago`}var kt={benchmark:{description:"Run performance benchmarks to test CLI performance",examples:[{command:"hydra benchmark",description:"Run full benchmark suite"},{command:"hydra benchmark --quick",description:"Run quick benchmark (1 iteration)"},{command:"hydra benchmark --startup-only",description:"Test only CLI startup time"},{command:"hydra benchmark --memory-only",description:"Test only memory usage"},{command:"hydra benchmark --worker-only",description:"Test only worker spawn performance"},{command:"hydra benchmark --iterations=10",description:"Run with 10 iterations"}],name:"hydra benchmark",notes:["Tests startup time, worker spawn time, memory usage, and command execution","Targets: startup <100ms, worker spawn <50ms, memory <100MB","Exit code 0 if score \u226570%, 1 if performance is below threshold"],options:[{description:"Number of benchmark iterations",flags:"--iterations",type:"number"},{description:"Number of workers to test",flags:"--workers",type:"number"},{description:"Test only CLI startup time",flags:"--startup-only",type:"boolean"},{description:"Test only memory usage",flags:"--memory-only",type:"boolean"},{description:"Test only worker spawn performance",flags:"--worker-only",type:"boolean"},{description:"Run quick benchmark (1 iteration)",flags:"--quick",type:"boolean"}],usage:"hydra benchmark [options]"},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]"}};function ln(r){if(r&&kt[r]){console.info(Xn(kt[r]));return}let n=[{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:"Run performance benchmarks to test CLI performance",name:"benchmark"},{description:"Show this help message",name:"help"}];console.info(Qn(`Hydra@${wr} - GitHub self-hosted runner manager`,"hydra <command> [options]",n,"Use hydra <command> --help for more information about a command."))}import{resolve as No}from"path";import{parseArgs as Io}from"util";var{$:yn}=globalThis.Bun;var rr=k({prefix:"hydra"}).child("init");async function vt(){let{toml:r}=Ho(),n=r?"hydra.toml":"hydra.json",t=No(process.cwd(),n);if(await Bun.file(t).exists()){let u=await H({initialValue:!1,message:`Configuration file ${n} already exists. Overwrite?`});if(A(u)||!u)on("Configuration cancelled"),process.exit(0)}Zn(E.cyan("\uD83D\uDE80 Hydra Configuration Setup")),rr.info("This will create a configuration file with your runner settings."),rr.info("You can always edit the file later or create additional profiles.");let e=await Jn({profileName:()=>T({message:"Profile name?",placeholder:"default"}),directory:()=>T({defaultValue:"./gh-runners",message:"Directory to store runners?",placeholder:"./gh-runners"}),name:()=>T({defaultValue:"runner",message:"Runner name prefix?",placeholder:"runner"}),labels:({results:u})=>{let l=u.name||"runner";return T({defaultValue:l,message:"Runner labels (comma-separated)?",placeholder:l})},numberOfMachines:()=>T({defaultValue:"1",message:"Number of runner machines?",placeholder:"1",validate:(u)=>{let l=Number.parseInt(u,10);if(Number.isNaN(l)||l<1)return"Please enter a valid number greater than 0";return}}),url:()=>T({message:"GitHub repository or organization URL? (optional)",placeholder:"https://github.com/org/repo"})},{onCancel:()=>{on("Configuration cancelled"),process.exit(0)}}),{profileName:s,labels:i,numberOfMachines:a,...f}=e,d={defaultProfile:s,profiles:{[s]:{...f,labels:i,numberOfMachines:Number.parseInt(a,10),os:"osx",overwrite:!1,run:!1}}},c=JSON.stringify(d,null,2);if(await Bun.write(t,c),await er(async()=>{await yn`chmod 600 ${t}`.quiet()},{logLevel:"warn",message:"Could not set secure file permissions"}),zn(E.green(`\u2713 Configuration saved to ${n}`)),rr.info("Example usage:"),rr.info(` hydra create -p ${s} --token YOUR_TOKEN${e.url?"":" --url REPO_URL"}`),rr.info("You can add more profiles by editing the configuration file."),e.url)await Ao(e.url)}async function Ao(r){let n=/github\.com[:/]([^/]+)(?:\/([^/.]+))?/,t=r.match(n);if(!t)return;let[,o,e]=t,i=`https://github.com/${e?`${o}/${e}`:`organizations/${o}`}/settings/actions/runners`;rr.info(`Opening GitHub settings: ${i}`),await er(async()=>{await yn`open ${i}`.quiet()},{fallback:async()=>{await er(async()=>{await yn`xdg-open ${i}`.quiet()},{fallback:()=>{rr.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"})}function Ho(){let{values:r}=Io({args:process.argv.slice(3),options:{toml:{default:!1,short:"t",type:"boolean"}},strict:!0});return r}import{parseArgs as So}from"util";var{$:Tt,Glob:Co}=globalThis.Bun;async function Wo(){let{values:r}=So({args:process.argv.slice(3),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 Nt(){let r=await Wo();if(!r.path&&!r.all)r.path=await T({message:"Path to configuration file:",placeholder:"./hydra.json",validate:(o)=>{if(!o)return"Path is required";return}});let n=await Mo(r);if(n.length===0){m.error("No configuration files found");return}m.info(`Found ${n.length} configuration file(s) to migrate`);let t=[];for(let o of n){let e=await Go(o,r);t.push(e)}Lo(t,r)}async function Mo(r){if(r.path){if(!await Bun.file(r.path).exists())throw new Error(`Configuration file not found: ${r.path}`);return[r.path]}if(r.all){let n=new Co("**/hydra.{json,toml}"),t=[];for await(let o of n.scan("."))if(!o.includes("node_modules")&&!o.includes(".git"))t.push(o);return t}return[]}async function Go(r,n){let t=K();t.start(`Migrating ${r}...`);try{let o=await Bun.file(r).text(),e=r.endsWith(".toml")?"toml":"json",s=n.format||e,i,a=[];if(e==="toml"){let d=`.temp-${Date.now()}.toml`;await Bun.write(d,o),i=(await import(d)).default,await Tt`rm ${d}`.quiet()}else i=JSON.parse(o);let f=await Uo(i,a);if(n.backup&&!n.dryRun){let d=`${r}.backup-${new Date().toISOString().replace(/:/g,"-")}`;await Bun.write(d,o),a.push(`Created backup at ${d}`)}if(!n.dryRun){let d=s!==e?r.replace(/\.(json|toml)$/,`.${s}`):r;if(s==="toml")await Po(d,f);else await Bun.write(d,JSON.stringify(f,null,2));if(d!==r){if(await H({initialValue:!0,message:`Remove original file ${r}?`}))await Tt`rm ${r}`.quiet(),a.push(`Removed original file ${r}`)}a.push(`Migrated to ${d}`)}return t.stop(`Migrated ${r}`),{changes:a,path:r,success:!0}}catch(o){return t.stop(`Failed to migrate ${r}`),{error:o.message,path:r,success:!1}}}async function Uo(r,n){let t={profiles:{}};if(r.defaultProfile)t.defaultProfile=r.defaultProfile;if(r.url||r.numberOfMachines||r.directory||r.labels){let o={};if(r.directory)o.directory=r.directory;if(r.labels)o.labels=r.labels;if(r.name)o.name=r.name;if(r.numberOfMachines)o.numberOfMachines=r.numberOfMachines;if(r.os)o.os=r.os;if(r.runnerGroup)o.runnerGroup=r.runnerGroup;if(r.url)o.url=r.url;if(r.overwrite!==void 0)o.overwrite=r.overwrite;if(r.run!==void 0)o.run=r.run;t.profiles.default=o,n.push("Migrated root-level settings to default profile"),delete r.url,delete r.numberOfMachines,delete r.directory,delete r.labels,delete r.name,delete r.os,delete r.runnerGroup,delete r.overwrite,delete r.run}if(r.profiles)for(let[o,e]of Object.entries(r.profiles)){let s=typeof e==="object"&&e!==null?{...e}:{};if(typeof e==="object"&&e!==null){if("runnerCount"in e&&!("numberOfMachines"in e))s.numberOfMachines=e.runnerCount,delete s.runnerCount,n.push(`Renamed 'runnerCount' to 'numberOfMachines' in profile '${o}'`);if("workDir"in e&&!("directory"in e))s.directory=e.workDir,delete s.workDir,n.push(`Renamed 'workDir' to 'directory' in profile '${o}'`);if(typeof e.labels==="string")s.labels=e.labels.split(",").map((i)=>i.trim()),n.push(`Converted labels to array format in profile '${o}'`)}t.profiles[o]=s}for(let[o,e]of Object.entries(r))if(!["profiles","defaultProfile"].includes(o))t[o]=e,n.push(`Preserved unknown property '${o}'`);return t}async function Po(r,n){let t="";if(n.defaultProfile)t+=`defaultProfile = "${n.defaultProfile}"
|
|
85
|
+
|
|
86
|
+
`;for(let[o,e]of Object.entries(n.profiles)){t+=`[profiles.${o}]
|
|
87
|
+
`;for(let[s,i]of Object.entries(e)){if(i===void 0||i===null)continue;if(typeof i==="string")t+=`${s} = "${i}"
|
|
88
|
+
`;else if(typeof i==="number")t+=`${s} = ${i}
|
|
89
|
+
`;else if(Array.isArray(i))t+=`${s} = [${i.map((a)=>`"${a}"`).join(", ")}]
|
|
90
|
+
`;else t+=`${s} = ${JSON.stringify(i)}
|
|
91
|
+
`}t+=`
|
|
92
|
+
`}await Bun.write(r,t.trim())}function Lo(r,n){if(m.info(""),n.dryRun)m.warn("DRY RUN MODE - No files were actually modified"),m.info("");let t=r.filter((e)=>e.success),o=r.filter((e)=>!e.success);if(t.length>0){m.success(`Successfully migrated ${t.length} file(s):`);for(let e of t)if(m.info(` ${y.value(e.path)}`),e.changes&&e.changes.length>0)for(let s of e.changes)m.info(` ${y.dim("\u2192")} ${s}`)}if(o.length>0){m.error(`Failed to migrate ${o.length} file(s):`);for(let e of o)m.error(` ${y.value(e.path)}: ${e.error}`)}m.info(""),m.info("Migration complete!")}import{parseArgs as qo}from"util";var{$:It}=globalThis.Bun;var L=x({prefix:"hydra:remove"});async function At(){let r=await Bo(),{directory:n,numberOfMachines:t,force:o}=r,{token:e,url:s}=r,i=`${n}/machines`;if(!await b.exists(i))throw w.createError(`Machines directory not found at ${i}. Nothing to remove.`,"FILE_SYSTEM_ERROR",void 0,{operation:"remove_machines",directory:n,machinesDir:i});if(e)L=x({prefix:"hydra:remove",secrets:[e]});if(!e&&!o){if(!s)throw L.warn("No token or URL provided. Runners will not be unregistered from GitHub."),L.warn("Use --force to remove runners without unregistering them."),new Error("Token (-t) and URL (-u) parameters are required or use --force");let a=Ko(s),f=await H({message:`No token provided. Would you like to open GitHub to get a runner token for unregistration?
|
|
93
|
+
${a}`});if(A(f)||!f)throw L.warn("Use --force to remove runners without unregistering them."),new Error("Token is required to unregister runners (or use --force)");L.info("Opening GitHub runner settings..."),await It`open ${a}`.quiet();let d=await T({message:"Enter the runner removal token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(c)=>{if(!c||c.trim().length===0)return"Token is required";return}});if(A(d))throw L.warn("Use --force to remove runners without unregistering them."),new Error("Token is required to unregister runners (or use --force)");e=d.trim()}if(e&&s)L.info("Unregistering runners from GitHub..."),await jo({directory:n,numberOfMachines:t,token:e});else if(!o)throw L.warn("No token or URL provided. Runners will not be unregistered from GitHub."),L.warn("Use --force to remove runners without unregistering them."),new Error("Token (-t) and URL (-u) parameters are required or use --force");await Vo({directory:n,numberOfMachines:t}),L.info("Runners successfully removed")}async function Bo(){let{values:r}=qo({args:process.argv.slice(3),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}),n=await G({configPath:r.config}),t=await U(n,r.profile),o={directory:r.directory,force:r.force,numberOfMachines:r.numberOfMachines,token:r.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url};if(t)return{directory:o.directory??t.directory??`${process.cwd()}/gh-runners`,force:o.force,numberOfMachines:o.numberOfMachines??String(t.numberOfMachines)??"1",token:o.token||t?.token,url:o.url??t.url};return o}async function jo({directory:r,numberOfMachines:n,token:t}){let o=x({prefix:"hydra:remove:unregister",secrets:[t]}),e=Number(n),s=(()=>{try{let l=Bun.spawnSync(["nproc"]);return Number.parseInt(l.stdout.toString().trim(),10)||4}catch{try{let l=Bun.spawnSync(["sysctl","-n","hw.ncpu"]);return Number.parseInt(l.stdout.toString().trim(),10)||4}catch{return 4}}})(),i=Math.min(Math.max(2,Math.floor(s/2)),e,8);o.info(`Unregistering ${e} runners with concurrency of ${i}`);let a=Array.from({length:e},(l,R)=>R+1).map((l)=>({execute:async()=>{let R=`${r}/machines/${l}`;if(!await b.exists(R))return o.debug(`Machine ${l} doesn't exist, skipping...`),{runnerIndex:l,status:"skipped"};try{return o.debug(`Unregistering machine ${l}...`),await It`${M(R)}/config.sh remove`.quiet().env({...process.env,RUNNER_CFG_PAT:t}),o.info(`Successfully unregistered machine ${l} from GitHub`),{runnerIndex:l,status:"success"}}catch(h){return o.warn(`Unable to unregister machine ${l}: ${h}`),{error:h,runnerIndex:l,status:"failed"}}},runnerIndex:l})),f=[];for(let l=0;l<a.length;l+=i){let R=a.slice(l,l+i),h=await Promise.allSettled(R.map((g)=>g.execute()));f.push(...h)}let d=f.filter((l)=>l.status==="fulfilled"&&l.value?.status==="success").length,c=f.filter((l)=>l.status==="fulfilled"&&l.value?.status==="failed").length,u=f.filter((l)=>l.status==="fulfilled"&&l.value?.status==="skipped").length;o.info(`Unregistration complete: ${d} successful, ${c} failed, ${u} skipped`)}async function Vo({directory:r,numberOfMachines:n}){let t=x({prefix:"hydra:remove:removeDirectories",secrets:[]}),o=Number(n),e=Array.from({length:o},(f,d)=>d+1).map((f)=>({execute:async()=>{let d=`${r}/machines/${f}`;if(!await b.exists(d))return{runnerIndex:f,status:"skipped"};try{return await b.deleteDirectory(d,{recursive:!0}),t.debug(`Removed machine ${f} directory`),{runnerIndex:f,status:"success"}}catch(c){return t.error(`Error removing machine ${f} directory: ${c}`),{error:c,runnerIndex:f,status:"failed"}}},runnerIndex:f})),s=await Promise.allSettled(e.map((f)=>f.execute())),i=s.filter((f)=>f.status==="fulfilled"&&f.value?.status==="success").length,a=s.filter((f)=>f.status==="fulfilled"&&f.value?.status==="failed").length;if(t.info(`Directory removal complete: ${i} removed, ${a} failed`),a>0)throw new Error(`Failed to remove ${a} runner directories`);try{let f=`${r}/machines`;if((await b.listDirectory(f)).length===0){if(await b.deleteDirectory(f,{recursive:!0}),(await b.listDirectory(r)).length===0)await b.deleteDirectory(r,{recursive:!0});L.info("Removed empty directories")}}catch(f){}}function Ko(r){try{let n=new URL(r),t=n.pathname.split("/").filter(Boolean);if(n.hostname==="github.com"||n.hostname==="www.github.com"){if(t[0]==="orgs"&&t[1])return`https://github.com/organizations/${t[1]}/settings/actions/runners`;if(t.length>=2)return`https://github.com/${t[0]}/${t[1]}/settings/actions/runners`}else{if(t[0]==="orgs"&&t[1])return`${n.origin}/organizations/${t[1]}/settings/actions/runners`;if(t.length>=2)return`${n.origin}/${t[0]}/${t[1]}/settings/actions/runners`}return r}catch{return r}}import{parseArgs as Zo}from"util";var{$:zo}=globalThis.Bun;var Wr=x({prefix:"runMachines"});async function Ht(){let r=await Jo(),{directory:n,numberOfMachines:t,name:o,labels:e,runnerGroup:s}=r,{token:i,url:a}=r;if(!a)throw w.createError("URL (-u) parameter is required","VALIDATION_ERROR",void 0,{operation:"run_machines",parameter:"url"});if(!i){let f=Xo(a),d=await H({message:`No token provided. Would you like to open GitHub to get a runner token?
|
|
94
|
+
${f}`});if(A(d)||!d)throw w.createError("Token is required to run machines","AUTHENTICATION_ERROR",void 0,{operation:"run_machines",parameter:"token"});Wr.info("Opening GitHub runner settings..."),await zo`open ${f}`.quiet();let c=await T({message:"Enter the runner registration token:",placeholder:"AXXXXXXXXXXXXXXXXXXXXXXXXX",validate:(u)=>{if(!u||u.trim().length===0)return"Token is required";return}});if(A(c))throw w.createError("Token is required to run machines","AUTHENTICATION_ERROR",void 0,{operation:"run_machines",parameter:"token"});i=c.trim()}if(Wr=x({prefix:"runMachines",secrets:[i]}),Wr.info(`Starting ${t} runners from ${n}`),Wr.debug(`Name: ${o}, Labels: ${e||"none"}`),!await b.exists(`${n}/machines`))throw w.createError(`Machines directory not found at ${n}/machines. Run 'hydra create' first.`,"FILE_SYSTEM_ERROR",void 0,{operation:"run_machines",directory:n,expectedPath:`${n}/machines`});await Yo({directory:n,labels:e,name:o,numberOfMachines:t,runnerGroup:s,token:i,url:a})}async function Jo(){let{values:r}=Zo({args:process.argv.slice(3),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}),n=await G({configPath:r.config}),t=await U(n,r.profile),o={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(t)return{directory:o.directory??t.directory??`${process.cwd()}/gh-runners`,labels:o.labels??t.labels,name:o.name??t.name??"runner",numberOfMachines:o.numberOfMachines??String(t.numberOfMachines)??"1",runnerGroup:o.runnerGroup??t.runnerGroup,token:o.token||t?.token,url:o.url??t.url};return o}async function Yo({directory:r,numberOfMachines:n,token:t,url:o,name:e,labels:s,runnerGroup:i}){let a=x({prefix:"runMachines:start",secrets:[t]});a.info(`Starting ${n} workers...`);let f=new D({maxRestarts:3,maxWorkers:Number(n),restartDelay:5000,restartOnError:!0});f.on("workerError",(c,u)=>{a.error(`Worker ${c.name} encountered error:`,u)}),f.on("workerExit",(c,u)=>{if(u!==0)a.warn(`Worker ${c.name} exited with code ${u}`)});let d=0;for(let c=1;c<=Number(n);c++){let u=`${r}/machines/${c}`;if(!await b.exists(u)){a.warn(`Machine ${c} doesn't exist, skipping...`);continue}let l=`${Ar()}/src/runner-worker.ts`,R=`${e}-${c}`,h=`runner-${c}`;try{await f.createWorker({data:{index:c,labels:s,machineCwd:u,name:e,runnerGroup:i,token:t,url:o},id:h,name:R,onError:(g)=>{a.error(`Worker ${R} error:`,g)},onExit:(g)=>{a.info(`Worker ${R} exited with code ${g}`)},onMessage:(g)=>{let N=g.type==="error"?"error":"info",nr="message"in g?g.message:`${g.type} event`;a[N](`${R}: ${nr}`)},scriptPath:l}),a.info(`Worker ${R} started successfully`),d++}catch(g){a.error(`Failed to start worker ${R}:`,g)}}if(d===0)throw w.createError("No workers could be started","WORKER_ERROR",void 0,{operation:"start_runners",directory:r,numberOfMachines:n});a.info(`${d} workers started. Press Ctrl+C to stop all machines`),process.on("SIGINT",async()=>{a.info("Gracefully shutting down workers..."),await f.shutdown(),process.exit(0)})}function Xo(r){try{let n=new URL(r),t=n.pathname.split("/").filter(Boolean);if(n.hostname==="github.com"||n.hostname==="www.github.com"){if(t[0]==="orgs"&&t[1])return`https://github.com/organizations/${t[1]}/settings/actions/runners/new`;if(t.length>=2)return`https://github.com/${t[0]}/${t[1]}/settings/actions/runners/new`}else{if(t[0]==="orgs"&&t[1])return`${n.origin}/organizations/${t[1]}/settings/actions/runners/new`;if(t.length>=2)return`${n.origin}/${t[0]}/${t[1]}/settings/actions/runners/new`}return r}catch{return r}}import{parseArgs as Qo}from"util";var{$:Fo}=globalThis.Bun;var dr=k({prefix:"hydra"}).child("status");async function St(){let r=await Do(),{directory:n,token:t,url:o,json:e}=r;if(!t||!o)throw new Error("Token (-t) and URL (-u) parameters are required");let s=K();s.start("Fetching runner status...");try{let i=await re(n),a=await ne(o,t),f=te(i,a);if(s.stop("Runner status fetched"),e)dr.info(JSON.stringify(f,null,2));else ie(f)}catch(i){throw s.stop("Failed to fetch runner status"),i}}async function Do(){let{values:r}=Qo({args:process.argv.slice(3),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}),n=await G({configPath:r.config}),t=await U(n,r.profile);return{directory:r.directory||t?.directory||`${process.cwd()}/gh-runners`,json:r.json,token:r.token||t?.token||process.env.GITHUB_TOKEN||process.env.RUNNER_TOKEN,url:r.url||t?.url}}async function re(r){let n=`${r}/machines`;return await er(async()=>{return(await Fo`ls ${n} 2>/dev/null || true`.quiet()).stdout.toString().trim().split(`
|
|
95
|
+
`).filter(Boolean)},{fallback:()=>{},logLevel:"debug",message:"No local runners found"})||[]}async function ne(r,n){let t=r.match(/github\.com[:/]([^/]+)(?:\/([^/.]+))?/);if(!t)throw new Error("Invalid GitHub URL");let[,o,e]=t,s=e?`https://api.github.com/repos/${o}/${e}/actions/runners`:`https://api.github.com/orgs/${o}/actions/runners`;return vr(async()=>{let i={Accept:"application/vnd.github.v3+json",Authorization:`Bearer ${n}`},a=await fetch(s,{headers:i});if(!a.ok)throw new Error(`GitHub API error: ${a.status} ${a.statusText}`);return await a.json()},{onRetry:(i,a)=>{m.warn(`Retrying GitHub API call (attempt ${i}): ${a.message}`)}})}function te(r,n){let t=[],o=new Map(n.runners.map((e)=>[e.name,e]));for(let e of r){let s=`runner-${e}`,i=o.get(s);if(i)t.push({busy:i.busy,labels:i.labels.map((a)=>a.name),name:s,os:i.os,status:i.busy?"busy":i.status==="online"?"online":"offline"});else t.push({busy:!1,labels:[],name:s,os:"unknown",status:"offline"})}return t}function ie(r){if(r.length===0){m.info("No runners found");return}dr.info("Runner Status:"),dr.info("\u2500".repeat(80));let n={busy:y.busy,offline:y.offline,online:y.online};for(let o of r){let e=n[o.status],s=o.status.toUpperCase().padEnd(7);dr.info(`${e("\u25CF")} ${e(s)} ${y.value(o.name.padEnd(20))} ${y.dim(`OS: ${o.os.padEnd(10)}`)} ${o.labels.length>0?y.dim(`Labels: ${o.labels.join(", ")}`):""}`)}dr.info("\u2500".repeat(80));let t={busy:r.filter((o)=>o.status==="busy").length,offline:r.filter((o)=>o.status==="offline").length,online:r.filter((o)=>o.status==="online").length,total:r.length};dr.info(`Summary: Total: ${t.total} | ${y.online(`Online: ${t.online}`)} | ${y.busy(`Busy: ${t.busy}`)} | ${y.offline(`Offline: ${t.offline}`)}`)}import{homedir as Ct}from"os";import{join as hn}from"path";import{parseArgs as oe}from"util";var Mr={global:hn(Ct(),".hydra","templates.json"),local:"./hydra-templates.json"};async function ee(){let{values:r}=oe({args:process.argv.slice(3),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}),n=r.action;if(n&&!["list","create","use","delete","show"].includes(n))throw new Error(`Unknown action: ${n}`);return{action:n,force:r.force,from:r.from,global:r.global,name:r.name}}async function Wt(){let r=await ee();if(!r.action)r.action=await X({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(r.action){case"list":await se();break;case"create":await ae(r);break;case"use":await fe(r);break;case"show":await de(r);break;case"delete":await ce(r);break;default:m.error(`Unknown action: ${r.action}`),m.info("Available actions: list, create, use, show, delete")}}async function J(r){let n=r?Mr.global:Mr.local,t=Bun.file(n);if(!await t.exists())return{templates:{},version:"1.0"};try{return await t.json()}catch{return{templates:{},version:"1.0"}}}async function Mt(r,n){let t=n?Mr.global:Mr.local;if(n){let o=hn(Ct(),".hydra");await Bun.write(hn(o,".gitkeep"),"")}await Bun.write(t,JSON.stringify(r,null,2))}async function se(){let r=await J(!0),n=await J(!1),t={...r.templates,...n.templates};if(Object.keys(t).length===0){m.info("No templates found"),m.info(""),m.info("Create a template with: hydra template create");return}m.info(y.value("Available Templates:")),m.info("");for(let[o,e]of Object.entries(t)){let i=o in r.templates?y.dim(" (global)"):"";if(m.info(` ${y.value(o)}${i}`),e.description)m.info(` ${y.dim(e.description)}`);if(e.extends)m.info(` ${y.dim(`Extends: ${e.extends}`)}`);let a=[];if(e.numberOfMachines)a.push(`machines: ${e.numberOfMachines}`);if(e.os)a.push(`os: ${e.os}`);if(e.labels)a.push(`labels: ${e.labels}`);if(a.length>0)m.info(` ${y.dim(a.join(", "))}`);m.info("")}}async function ae(r){let n=r.name||await T({message:"Template name:",placeholder:"my-template",validate:(c)=>{if(!c)return"Template name is required";if(!/^[a-zA-Z0-9-_]+$/.test(c))return"Template name can only contain letters, numbers, hyphens, and underscores";return}}),t=await J(r.global??!1);if(!r.force&&n in t.templates){if(!await H({initialValue:!1,message:`Template '${n}' already exists. Overwrite?`})){m.info("Template creation cancelled");return}}let o=await T({message:"Description (optional):",placeholder:"Template for production runners"}),e={};if(r.from){let c=t.templates[r.from];if(c)e={...c},delete e.name,delete e.description,delete e.metadata,delete e.extends}let s=await T({initialValue:e.numberOfMachines?.toString()||"1",message:"Number of machines:",placeholder:e.numberOfMachines?.toString()||"1"}),i=await X({initialValue:e.os||"osx",message:"Operating system:",options:[{label:"macOS",value:"osx"},{label:"Linux",value:"linux"},{label:"Windows",value:"windows"}]}),a=await T({initialValue:e.labels,message:"Labels (comma-separated, optional):",placeholder:e.labels||"self-hosted,x64"}),f=await T({initialValue:e.directory||"./gh-runners",message:"Runner directory:",placeholder:e.directory||"./gh-runners"}),d={description:o||void 0,directory:f,extends:r.from||void 0,labels:a||void 0,metadata:{author:process.env.USER||void 0,created:new Date().toISOString(),updated:new Date().toISOString()},name:n,numberOfMachines:Number.parseInt(s,10),os:i};t.templates[n]=d,await Mt(t,r.global??!1),m.success(`Template '${n}' created successfully`),m.info(""),m.info(`Use it with: hydra create --template ${n}`)}async function fe(r){let n=await J(!0),t=await J(!1),o={...n.templates,...t.templates};if(Object.keys(o).length===0){m.error("No templates found"),m.info("Create a template with: hydra template create");return}let e=r.name||await X({message:"Select a template:",options:Object.entries(o).map(([f,d])=>({label:`${f}${d.description?` - ${d.description}`:""}`,value:f}))}),s=o[e];if(!s){m.error(`Template '${e}' not found`);return}let i=await Rn(s,o);if(m.info(""),m.info(y.value(`Using template: ${e}`)),m.info(""),m.info("This will create runners with the following configuration:"),m.info(` Number of machines: ${i.numberOfMachines||1}`),m.info(` OS: ${i.os||"osx"}`),m.info(` Directory: ${i.directory||"./gh-runners"}`),i.labels)m.info(` Labels: ${i.labels}`);m.info("");let a=await X({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(a==="command"){let f=[];if(i.numberOfMachines)f.push(`-m ${i.numberOfMachines}`);if(i.os)f.push(`-s ${i.os}`);if(i.directory)f.push(`-d "${i.directory}"`);if(i.labels)f.push(`-l "${i.labels}"`);if(i.name)f.push(`-n "${i.name}"`);m.info("Run the following command:"),m.info(""),m.info(y.value(`hydra create ${f.join(" ")} -t <TOKEN> -u <URL>`)),m.info("")}else{let f={defaultProfile:"default",profiles:{default:i}},d=a==="json"?"hydra.json":"hydra.toml";if(a==="json")await Bun.write(d,JSON.stringify(f,null,2));else{let c=`defaultProfile = "default"
|
|
96
|
+
|
|
97
|
+
[profiles.default]
|
|
98
|
+
`;for(let[u,l]of Object.entries(i))if(l!==void 0&&l!==null)if(typeof l==="string")c+=`${u} = "${l}"
|
|
99
|
+
`;else c+=`${u} = ${l}
|
|
100
|
+
`;await Bun.write(d,c)}m.success(`Created ${d}`),m.info(""),m.info("Now run:"),m.info(y.value("hydra create -t <TOKEN> -u <URL>"))}}async function de(r){let n=await J(!0),t=await J(!1),o={...n.templates,...t.templates},e=r.name||await X({message:"Select a template:",options:Object.entries(o).map(([a,f])=>({label:`${a}${f.description?` - ${f.description}`:""}`,value:a}))}),s=o[e];if(!s){m.error(`Template '${e}' not found`);return}let i=await Rn(s,o);if(m.info(""),m.info(y.value(`Template: ${e}`)),m.info("\u2500".repeat(40)),s.description)m.info(`Description: ${s.description}`);if(s.extends)m.info(`Extends: ${s.extends}`);if(s.metadata){if(s.metadata.author)m.info(`Author: ${s.metadata.author}`);if(s.metadata.created)m.info(`Created: ${new Date(s.metadata.created).toLocaleDateString()}`);if(s.metadata.updated)m.info(`Updated: ${new Date(s.metadata.updated).toLocaleDateString()}`);if(s.metadata.tags?.length)m.info(`Tags: ${s.metadata.tags.join(", ")}`)}m.info(""),m.info("Configuration:"),m.info(JSON.stringify(i,null,2))}async function ce(r){let n=await J(r.global??!1);if(Object.keys(n.templates).length===0){m.error("No templates found");return}let t=r.name||await X({message:"Select a template to delete:",options:Object.entries(n.templates).map(([o,e])=>({label:`${o}${e.description?` - ${e.description}`:""}`,value:o}))});if(!(t in n.templates)){m.error(`Template '${t}' not found`);return}if(!r.force){if(!await H({initialValue:!1,message:`Are you sure you want to delete template '${t}'?`})){m.info("Deletion cancelled");return}}delete n.templates[t],await Mt(n,r.global??!1),m.success(`Template '${t}' deleted`)}async function Rn(r,n,t=new Set){if(t.has(r.name))throw new Error(`Circular template dependency detected: ${r.name}`);t.add(r.name);let o={};if(r.extends){let d=n[r.extends];if(d)o=await Rn(d,n,t)}let{name:e,description:s,extends:i,metadata:a,...f}=r;return{...o,...f}}import{parseArgs as ue}from"util";var Gt=k({prefix:"config-validator"});class Ut{validateConfig(r){let n={errors:[],valid:!0,warnings:[]};if(!r||typeof r!=="object")return n.valid=!1,n.errors.push({code:"INVALID_CONFIG",field:"config",message:"Configuration must be an object"}),n;if(!r.profiles||typeof r.profiles!=="object")return n.valid=!1,n.errors.push({code:"MISSING_PROFILES",field:"profiles",message:"Configuration must have a profiles object"}),n;return this.validateProfiles(r.profiles,n),this.validateDefaultProfile(r.defaultProfile,r.profiles,n),n}validateProfile(r){let n={errors:[],valid:!0,warnings:[]};return this.validateProfileFields(r,n),n}validateProfiles(r,n){if(Object.keys(r).length===0){n.valid=!1,n.errors.push({code:"NO_PROFILES",field:"profiles",message:"At least one profile is required"});return}for(let[o,e]of Object.entries(r)){if(!e||typeof e!=="object"){n.valid=!1,n.errors.push({code:"INVALID_PROFILE",field:`profiles.${o}`,message:"Profile must be an object"});continue}let s=this.validateProfile(e);if(!s.valid)n.valid=!1,n.errors.push(...s.errors.map((i)=>({...i,field:`profiles.${o}.${i.field}`})));n.warnings.push(...s.warnings.map((i)=>({...i,field:`profiles.${o}.${i.field}`})))}}validateDefaultProfile(r,n,t){if(r){if(!n[r])t.valid=!1,t.errors.push({code:"DEFAULT_PROFILE_NOT_FOUND",field:"defaultProfile",message:`Default profile "${r}" not found in profiles`})}}validateProfileFields(r,n){if(r.numberOfMachines!==void 0){if(typeof r.numberOfMachines!=="number")n.valid=!1,n.errors.push({code:"INVALID_TYPE",field:"numberOfMachines",message:"Number of machines must be a number"});else if(r.numberOfMachines<1)n.valid=!1,n.errors.push({code:"INVALID_NUMBER_OF_MACHINES",field:"numberOfMachines",message:"Number of machines must be at least 1"});else if(r.numberOfMachines>100)n.warnings.push({code:"LARGE_NUMBER_OF_MACHINES",field:"numberOfMachines",message:"Large number of machines may impact performance"})}if(r.os!==void 0){let t=["osx","linux","windows"];if(!t.includes(r.os))n.valid=!1,n.errors.push({code:"INVALID_OS",field:"os",message:`Invalid OS "${r.os}". Must be one of: ${t.join(", ")}`})}if(r.directory!==void 0){if(typeof r.directory!=="string")n.valid=!1,n.errors.push({code:"INVALID_TYPE",field:"directory",message:"Directory must be a string"});else if(!r.directory.startsWith("/")&&!r.directory.match(/^[A-Z]:\\/)&&!r.directory.startsWith("./")&&!r.directory.startsWith("~"))n.warnings.push({code:"RELATIVE_PATH_WARNING",field:"directory",message:"Directory path should be absolute or relative (starting with ./ or ~/)"})}if(r.url!==void 0&&typeof r.url==="string")try{if(!new URL(r.url).hostname.includes("github.com"))n.warnings.push({code:"NON_GITHUB_URL",field:"url",message:"URL does not appear to be a GitHub URL"})}catch{n.valid=!1,n.errors.push({code:"INVALID_URL",field:"url",message:"Invalid URL format"})}if(r.token!==void 0&&typeof r.token==="string"){if(r.token.length<10)n.warnings.push({code:"SHORT_TOKEN",field:"token",message:"Token appears to be too short"})}}}function me(){return new Ut}function Rr(r){return me().validateConfig(r)}function Pt(r){let n=Rr(r);for(let t of n.errors)Gt.error(`${t.field}: ${t.message}`);for(let t of n.warnings)Gt.warn(`${t.field}: ${t.message}`);return n}async function pe(){let{values:r}=ue({args:process.argv.slice(3),options:{config:{short:"c",type:"string"},fix:{default:!1,short:"f",type:"boolean"},json:{default:!1,short:"j",type:"boolean"}},strict:!0});return{configPath:r.config,fix:r.fix,json:r.json}}async function Lt(){let r=await pe(),n=r.configPath||await fn();if(!n)throw w.createError("No configuration file found. Create one with: hydra init","CONFIG_ERROR",void 0,{operation:"validate"});if(!await b.exists(n))throw w.createError(`Configuration file not found: ${n}`,"FILE_SYSTEM_ERROR",void 0,{operation:"validate",configPath:n});m.info(`Validating configuration: ${y.dim(n)}`);try{let t=await b.readFile(n),o=n.endsWith(".toml"),e;if(o)e=Bun.TOML.parse(t);else e=JSON.parse(t);if(r.json){let i=Rr(e);console.log(JSON.stringify(i,null,2)),process.exit(i.valid?0:1)}let s=Pt(e);if(r.fix&&!s)if(m.info(`
|
|
101
|
+
Attempting to fix configuration issues...`),await le(e,n))m.success("Configuration issues fixed and saved");else m.error("Unable to automatically fix all issues"),m.info("Please manually review and update your configuration");process.exit(s?0:1)}catch(t){if(t instanceof SyntaxError)throw w.createError(`Configuration file has syntax errors: ${t.message}`,"CONFIG_ERROR",void 0,{operation:"validate",configPath:n},t);else throw w.handleError(t,{operation:"validate",configPath:n})}}async function le(r,n){let t=Rr(r);if(!r.profiles)r.profiles={};for(let e of t.errors){if(e.field==="defaultProfile"&&r.defaultProfile)delete r.defaultProfile,m.info("Removed invalid defaultProfile");if(e.field?.startsWith("profiles.")&&e.field?.includes(".numberOfMachines")){let i=e.field.split(".")[1];if(i&&r.profiles[i]){let a=r.profiles[i].numberOfMachines,f=Number.parseInt(String(a),10);if(Number.isNaN(f)||f<1)r.profiles[i].numberOfMachines="1",m.info(`Fixed numberOfMachines for profile '${i}'`)}}if(e.field?.startsWith("profiles.")&&e.field?.includes(".labels")){let i=e.field.split(".")[1];if(i&&r.profiles[i]&&r.profiles[i].labels){let a=r.profiles[i].labels.split(",").map((f)=>f.trim()).filter((f)=>f.match(/^[a-zA-Z0-9\-_]+$/)).join(",");r.profiles[i].labels=a,m.info(`Fixed labels for profile '${i}'`)}}}if(Rr(r).valid){let s=n.endsWith(".toml")?JSON.stringify(r,null,2):JSON.stringify(r,null,2);return await b.writeFile(n,s),!0}return!1}import{watch as ye}from"fs";import{parseArgs as he}from"util";var Y=x({prefix:"watch"});async function Re(){let{values:r}=he({args:process.argv.slice(3),options:{command:{default:"status",short:"C",type:"string"},config:{short:"c",type:"string"},debounce:{default:"1000",type:"string"},directory:{default:"./gh-runners",short:"d",type:"string"},exclude:{default:[],multiple:!0,type:"string"},profile:{short:"p",type:"string"}},strict:!0}),n=await G({configPath:r.config}),t=await U(n,r.profile);return ht(t,{command:r.command,debounce:Number.parseInt(r.debounce,10),directory:r.directory,exclude:r.exclude})}async function qt(){let r=await Re();if(!await b.exists(r.directory))Y.error(`Directory not found: ${r.directory}`),process.exit(1);Y.info(`Watching ${r.directory} for changes...`),Y.info(`Will run: hydra ${r.command}`),Y.info(`Debounce: ${r.debounce}ms`);let n=K(),t=null,o=!1,e=async()=>{if(o)return;o=!0,n.start(`Running: hydra ${r.command}`);try{let{$:a}=awaitPromise.resolve(globalThis.Bun),f=await a`hydra ${r.command} -d ${r.directory}`.quiet();if(f.exitCode===0)n.stop(y.success("\u2713 Command completed successfully"));else n.stop(y.error(`\u2717 Command failed with exit code ${f.exitCode}`)),Y.error(f.stderr.toString())}catch(a){n.stop(y.error("\u2717 Command failed")),Y.error("Error running command:",a)}finally{o=!1}},s=(a,f)=>{if(!f)return;if(r.exclude.some((c)=>{if(c.includes("*"))return new RegExp(c.replace(/\*/g,".*")).test(f);return f.includes(c)}))return;if(Y.info(`Detected ${a}: ${f}`),t)clearTimeout(t);t=setTimeout(()=>{e()},r.debounce)};await e();let i=ye(r.directory,{recursive:!0},s);process.on("SIGINT",()=>{Y.info(`
|
|
102
|
+
Stopping watch mode...`),i.close(),process.exit(0)}),await new Promise(()=>{})}var gn={benchmark:mt,create:$t,health:Ot,help:async()=>ln(),init:vt,migrate:Nt,remove:At,run:Ht,status:St,template:Wt,validate:Lt,watch:qt},ge={b:"benchmark",c:"create",h:"help",i:"init",r:"run",rm:"remove",s:"status",w:"watch"};async function we(){let n=process.argv.slice(2)[0]?.toLowerCase();if(!n||n==="--help"||n==="-h")ln(),process.exit(0);if(n==="--version"||n==="-v"||n==="version")console.log(wr),process.exit(0);let t=ge[n]||n,o=gn[t];if(!o)console.error(`Unknown command: ${n}`),console.error(`
|
|
103
|
+
Available commands: ${Object.keys(gn).sort().join(", ")}`),process.exit(1);let e=["benchmark","create","health","help","init","migrate","remove","run","status","template","validate","watch"];for(let s of e)if(!(s in gn))throw new Error(`Missing command implementation: ${s}`);try{await o()}catch(s){let i=w.handleError(s,{command:t});if(console.error(w.formatError(i)),process.env.DEBUG||process.env.HYDRA_DEBUG)console.error(`
|
|
104
|
+
Debug Information:`),console.error(w.formatDebugError(i));process.exit(1)}}await we();
|
package/package.json
CHANGED
|
@@ -28,16 +28,20 @@
|
|
|
28
28
|
"registry": "https://registry.npmjs.org/"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
|
+
"analyze": "bun src/lib/bundle-analyzer.ts",
|
|
32
|
+
"benchmark": "bun src/scripts/benchmark.ts",
|
|
31
33
|
"build": "rm -rf dist && bun build.ts",
|
|
32
34
|
"clean": "rm -rf dist node_modules",
|
|
33
35
|
"dev": "bun --bun src/cli.ts",
|
|
34
36
|
"package:dryRun": "bun run package:prepare && bun publish --dry-run --no-git-checks --access public --force && bun install",
|
|
35
37
|
"package:prepare": "NODE_ENV=production bun run build && bun ../../tools/scripts/prepare-publish.ts .",
|
|
36
38
|
"package:publish": "bun run package:prepare && bun publish --access public --no-git-checks && bun install",
|
|
39
|
+
"test": "bun test",
|
|
40
|
+
"test:chaos": "bun test src/__tests__/chaos.test.ts",
|
|
37
41
|
"type-check": "bun --bun tsc --noEmit",
|
|
38
42
|
"type-check:go": "tsgo"
|
|
39
43
|
},
|
|
40
44
|
"type": "module",
|
|
41
45
|
"types": "src/cli.ts",
|
|
42
|
-
"version": "0.5.
|
|
46
|
+
"version": "0.5.2"
|
|
43
47
|
}
|