@r5n/hydra 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -125
- package/dist/cli.js +94 -93
- package/package.json +1 -8
- package/schema.json +78 -4
package/README.md
CHANGED
|
@@ -1,182 +1,136 @@
|
|
|
1
1
|
# Hydra
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Spawn and manage local self-hosted GitHub Actions runners.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@r5n/hydra)
|
|
6
|
-
[](./LICENSE)
|
|
7
|
-

|
|
5
|
+
[](https://www.npmjs.com/package/@r5n/hydra) [](./LICENSE)
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
Hydra registers runners against a GitHub repository or organization and runs them as background processes on the machine it runs on. All state lives in a `.hydra/` directory relative to your current working directory, so each directory you run it from is its own isolated runner fleet.
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
## Requirements
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
- Bun (the published CLI runs on Bun)
|
|
12
|
+
- `gh` CLI, installed and authenticated (`gh auth login`) — Hydra mints runner registration and removal tokens via `gh api`; it never asks for or stores a token itself. Repository runners need admin access to the repository; organization runners need the `admin:org` scope.
|
|
13
|
+
- `bash`, `curl`, `tar`
|
|
14
|
+
- macOS (Apple Silicon) or Linux (x64). A `win-x64` runner download mapping exists in the code, but registration and startup shell out to `bash config.sh` / `bash run.sh`, so Windows is not actually supported.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
|
-
# Install
|
|
17
19
|
bun add -g @r5n/hydra
|
|
20
|
+
```
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
hydra init
|
|
21
|
-
|
|
22
|
-
# Create runners
|
|
23
|
-
hydra create -t $TOKEN -u https://github.com/org/repo -m 3
|
|
22
|
+
## Quick start
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
```bash
|
|
25
|
+
mkdir ~/runners && cd ~/runners
|
|
26
|
+
hydra init https://github.com/owner/repo -c 2
|
|
27
|
+
hydra create
|
|
28
|
+
hydra start
|
|
29
|
+
hydra status
|
|
27
30
|
```
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
Bare `hydra` prints help. `hydra -i` opens an interactive menu that walks through the same commands with prompts. `hydra help <command>` or `hydra <command> --help` shows per-command usage.
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
## Commands
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
- Reusable profile configs
|
|
35
|
-
- Monitor runner status
|
|
36
|
-
- Cross-platform (macOS, Linux, Windows)
|
|
36
|
+
### init
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
`hydra init [url]` writes a profile to `.hydra/config.json`. The first profile becomes the default. Run with no arguments it opens an interactive form; when any positional or piped input is involved the URL is required.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
- `-p, --profile` profile name (default: `default`)
|
|
41
|
+
- `-n, --name` base name for runners (default: `runner`)
|
|
42
|
+
- `-c, --runners` number of runners (default: 1)
|
|
43
|
+
- `-l, --labels` comma-separated extra labels
|
|
44
|
+
- `-f, --force` overwrite an existing profile
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
### create
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
hydra init # Interactive
|
|
46
|
-
hydra init --toml # Use TOML format
|
|
47
|
-
```
|
|
48
|
+
`hydra create [profile] [count]` downloads the latest `actions/runner` release (once per version, shared across runners), then registers runners named `<name>-1`, `<name>-2`, … It tops up to the target count: if the profile already has enough runners recorded, it does nothing. `count` overrides the profile's `numberOfMachines`.
|
|
48
49
|
|
|
49
|
-
###
|
|
50
|
+
### start / stop
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
`hydra start [profile] [ids...]` launches each runner's `run.sh` as a detached background process and records its pid. `hydra stop [profile] [ids...]` kills them. Omit the ids to target every runner in the profile; omit the profile to use the default. Runners do not survive a reboot — run `hydra start` again.
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
# Basic
|
|
55
|
-
hydra create -t TOKEN -u REPO_URL
|
|
54
|
+
### status
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
hydra create -t TOKEN -u REPO_URL -m 5 -l "docker,gpu"
|
|
56
|
+
`hydra status` lists every profile's runners with their state (`running` with pid, `registered`, or `unknown`). State is determined locally from pid liveness and the runner's `.runner` file; no API calls.
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
hydra create -p production -t TOKEN
|
|
62
|
-
```
|
|
58
|
+
### logs
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
- `-t, --token` — GitHub PAT (required)
|
|
66
|
-
- `-u, --url` — Repo/org URL (required)
|
|
67
|
-
- `-m, --numberOfMachines` — Number of runners (default: 1)
|
|
68
|
-
- `-n, --name` — Runner name prefix
|
|
69
|
-
- `-l, --labels` — Comma-separated labels
|
|
70
|
-
- `-d, --directory` — Runners directory
|
|
71
|
-
- `-o, --os` — OS: osx, linux, windows
|
|
72
|
-
- `-p, --profile` — Use config profile
|
|
60
|
+
`hydra logs [id]` tails the newest job log (`Worker_*.log`) from the runner's `_diag` directory. If no job has run yet it falls back to the runner daemon log with a warning. The id can be omitted when there is exactly one runner.
|
|
73
61
|
|
|
74
|
-
|
|
62
|
+
- `-n, --lines` lines to tail (default: 100)
|
|
63
|
+
- `-r, --runner` show the runner daemon log (`Runner_*.log`) instead of the job log
|
|
64
|
+
- `-l, --list` list available log files with timestamps and sizes
|
|
65
|
+
- `-o, --open` open the log in `$EDITOR` (falls back to `open` on macOS)
|
|
75
66
|
|
|
76
|
-
|
|
67
|
+
### cleanup
|
|
77
68
|
|
|
78
|
-
|
|
79
|
-
hydra run -t TOKEN -u REPO_URL -m 3
|
|
80
|
-
hydra run -p production -t TOKEN
|
|
81
|
-
```
|
|
69
|
+
`hydra cleanup` frees disk space. By default it prunes `_diag` log files older than 7 days (always keeping the newest runner and worker log per runner) and removes shared runner versions no runner's `externals` link points to (the newest installed version is always kept). `_work` holds job checkouts and caches, so it is never cleaned by default — pass `-w` explicitly. Runners that are currently running are skipped for `_work` cleanup.
|
|
82
70
|
|
|
83
|
-
|
|
71
|
+
- `-l, --logs` prune old `_diag` log files
|
|
72
|
+
- `-w, --work` delete `_work` contents of stopped runners
|
|
73
|
+
- `-s, --shared` remove unused shared runner versions
|
|
74
|
+
- `-d, --days` age threshold in days for log pruning (default: 7, or `cleanup.olderThanDays`)
|
|
75
|
+
- `-n, --dry-run` list what would be deleted with sizes, delete nothing
|
|
76
|
+
- `-y, --yes` skip confirmation prompts
|
|
84
77
|
|
|
85
|
-
|
|
78
|
+
Passing any of `-l`/`-w`/`-s` cleans only those targets; with none, the targets come from the `cleanup` config section (default: logs and shared).
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
hydra remove -t TOKEN -u REPO_URL -m 3
|
|
89
|
-
hydra remove -p production -t TOKEN -f # Force without unregistering
|
|
90
|
-
```
|
|
80
|
+
### update
|
|
91
81
|
|
|
92
|
-
|
|
82
|
+
`hydra update` checks the latest `actions/runner` release, and if it differs from the installed version, swaps the binaries for every runner. Runners that were running are stopped, updated, and restarted.
|
|
93
83
|
|
|
94
|
-
|
|
84
|
+
### remove
|
|
95
85
|
|
|
96
|
-
|
|
97
|
-
hydra status -t TOKEN -u REPO_URL
|
|
98
|
-
hydra status -p production -t TOKEN --json
|
|
99
|
-
```
|
|
86
|
+
`hydra remove [profile] [ids...]` stops the runners, deregisters them from GitHub, and deletes their directories.
|
|
100
87
|
|
|
101
|
-
|
|
88
|
+
### profile
|
|
102
89
|
|
|
103
|
-
|
|
90
|
+
- `hydra profile list` — profiles with URL, OS, and created/running counts
|
|
91
|
+
- `hydra profile default <name>` — set the default profile
|
|
92
|
+
- `hydra profile remove <name>` — remove a profile; if it has runners, stops and deregisters them first (after confirmation)
|
|
104
93
|
|
|
105
|
-
|
|
94
|
+
## Configuration
|
|
95
|
+
|
|
96
|
+
`.hydra/config.json`, resolved relative to the working directory. Hydra writes it; the `profiles` section is safe to edit by hand:
|
|
106
97
|
|
|
107
98
|
```json
|
|
108
99
|
{
|
|
100
|
+
"defaultProfile": "default",
|
|
109
101
|
"profiles": {
|
|
110
|
-
"
|
|
111
|
-
"url": "https://github.com/
|
|
112
|
-
"name": "
|
|
113
|
-
"numberOfMachines": 3,
|
|
114
|
-
"labels": "linux,docker",
|
|
115
|
-
"directory": "/opt/runners",
|
|
116
|
-
"os": "linux"
|
|
117
|
-
},
|
|
118
|
-
"dev": {
|
|
119
|
-
"url": "https://github.com/org/dev-repo",
|
|
120
|
-
"name": "dev-runner",
|
|
102
|
+
"default": {
|
|
103
|
+
"url": "https://github.com/owner/repo",
|
|
104
|
+
"name": "runner",
|
|
121
105
|
"numberOfMachines": 2,
|
|
122
|
-
"labels": "
|
|
106
|
+
"labels": "macOS,ARM64",
|
|
107
|
+
"directory": ".hydra/runners",
|
|
108
|
+
"os": "osx",
|
|
109
|
+
"provider": "github",
|
|
110
|
+
"overwrite": false,
|
|
111
|
+
"run": false
|
|
123
112
|
}
|
|
124
113
|
},
|
|
125
|
-
"
|
|
114
|
+
"runners": []
|
|
126
115
|
}
|
|
127
116
|
```
|
|
128
117
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
hydra create -p production -t $TOKEN
|
|
133
|
-
hydra status -p dev -t $TOKEN
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Environment Variables
|
|
137
|
-
|
|
138
|
-
- `GITHUB_PERSONAL_ACCESS_TOKEN` — Default token
|
|
139
|
-
- `HYDRA_CONFIG` — Config file path
|
|
140
|
-
|
|
141
|
-
## Token Permissions
|
|
142
|
-
|
|
143
|
-
- **Repository runners:** `repo` scope
|
|
144
|
-
- **Organization runners:** `admin:org` scope
|
|
118
|
+
`os` is one of `osx` | `linux` | `windows` (auto-detected by `init`). An optional `runnerGroup` string is passed through to `config.sh --runnergroup`; runner groups only apply to organization runners. The `runners` array is Hydra's record of what it created — leave it alone.
|
|
145
119
|
|
|
146
|
-
|
|
120
|
+
An optional `cleanup` section controls `hydra cleanup` and automatic cleanup:
|
|
147
121
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
# Development setup
|
|
152
|
-
hydra create -p dev -t $TOKEN -m 2
|
|
153
|
-
|
|
154
|
-
# Production with specific labels
|
|
155
|
-
hydra create -p prod -t $TOKEN -l "deploy,production"
|
|
156
|
-
|
|
157
|
-
# Monitor all runners
|
|
158
|
-
hydra status -p prod -t $TOKEN --json | jq '.[] | select(.status == "offline")'
|
|
159
|
-
|
|
160
|
-
# Cleanup
|
|
161
|
-
hydra remove -p dev -t $TOKEN
|
|
122
|
+
```json
|
|
123
|
+
"cleanup": { "auto": true, "intervalHours": 24, "olderThanDays": 7, "targets": ["logs", "shared"] }
|
|
162
124
|
```
|
|
163
125
|
|
|
164
|
-
|
|
126
|
+
All fields are optional; the values above (with `auto: false`) are the defaults. With `auto` enabled, `hydra start` and `hydra update` run a cleanup afterwards whenever the last run is more than `intervalHours` ago. Automatic runs never prompt and only touch the configured `targets` — `work` only if you list it explicitly. Hydra records `lastRun` itself; leave it alone.
|
|
165
127
|
|
|
166
|
-
|
|
167
|
-
- Check token has `repo` or `admin:org` scope
|
|
168
|
-
- Verify token isn't expired
|
|
128
|
+
The `url` is either a repository URL (`https://github.com/owner/repo`) or an organization URL (`https://github.com/org`). Repository URLs mint tokens from the repository endpoint (requires repo admin); organization URLs use the organization endpoint (requires the `admin:org` scope).
|
|
169
129
|
|
|
170
|
-
|
|
171
|
-
- Check network connectivity
|
|
172
|
-
- Verify GitHub URL format
|
|
173
|
-
- Ensure write permissions in runner directory
|
|
130
|
+
## How it works
|
|
174
131
|
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
DEBUG=* hydra create -t TOKEN -u URL
|
|
178
|
-
```
|
|
132
|
+
Runner binaries are downloaded once per version into `.hydra/shared/github/<version>`. Each runner directory under `.hydra/runners/<id>` gets hardlinks for `bin`, a symlink for `externals`, and its own copies of the shell scripts, so ten runners cost roughly one copy of the runner distribution on disk. Start/stop is plain process management: a detached `bash run.sh` plus a pid file per runner.
|
|
179
133
|
|
|
180
134
|
## License
|
|
181
135
|
|
|
182
|
-
Apache
|
|
136
|
+
Apache-2.0 — see [LICENSE](./LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -1,98 +1,99 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
4
|
-
`),
|
|
5
|
-
`){if(
|
|
6
|
-
`){if(
|
|
7
|
-
`)}var
|
|
8
|
-
`),
|
|
9
|
-
`),i=
|
|
10
|
-
`),
|
|
11
|
-
`).map((
|
|
12
|
-
`)}function
|
|
13
|
-
`),
|
|
14
|
-
`).length-1;this.output.write(
|
|
15
|
-
`);this.output.write(
|
|
16
|
-
`).slice(
|
|
17
|
-
`)),this._prevFrame=r;return}}this.output.write(W.erase.down())}this.output.write(r),this.state==="initial"&&(this.state="active"),this._prevFrame=r}}}function Li(r,n){if(r===void 0||n.length===0)return 0;let o=n.findIndex((i)=>i.value===r);return o!==-1?o:0}function Ii(r,n){return(n.label??String(n.value)).toLowerCase().includes(r.toLowerCase())}function Di(r,n){if(n)return r?n:n[0]}var Ri=class extends T{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#n=0;#e="";#r;#t;#s;get cursor(){return this.#n}get userInputWithCursor(){if(!this.userInput)return jr(["inverse","hidden"],"_");if(this._cursor>=this.userInput.length)return`${this.userInput}\u2588`;let n=this.userInput.slice(0,this.cursor),o=this.userInput.slice(this.cursor,this.cursor+1),i=this.userInput.slice(this.cursor+1);return`${n}${jr("inverse",o)}${i}`}get options(){return typeof this.#t=="function"?this.#t():this.#t}constructor(n){super(n),this.#t=n.options,this.#s=n.placeholder;let o=this.options;this.filteredOptions=[...o],this.multiple=n.multiple===!0,this.#r=typeof n.options=="function"?n.filter:n.filter??Ii;let i;if(n.initialValue&&Array.isArray(n.initialValue)?this.multiple?i=n.initialValue:i=n.initialValue.slice(0,1):!this.multiple&&this.options.length>0&&(i=[this.options[0]?.value]),i)for(let e of i){let t=o.findIndex((a)=>a.value===e);t!==-1&&(this.toggleSelected(e),this.#n=t)}this.focusedValue=this.options[this.#n]?.value,this.on("key",(e,t)=>this.#o(e,t)),this.on("userInput",(e)=>this.#i(e))}_isActionKey(n,o){return n==="\t"||this.multiple&&this.isNavigating&&o.name==="space"&&n!==void 0&&n!==""}#o(n,o){let i=o.name==="up",e=o.name==="down",t=o.name==="return",a=this.userInput===""||this.userInput==="\t",s=this.#s,c=this.options,f=s!==void 0&&s!==""&&c.some((d)=>!d.disabled&&(this.#r?this.#r(s,d):!0));if(o.name==="tab"&&a&&f){this.userInput==="\t"&&this._clearUserInput(),this._setUserInput(s,!0),this.isNavigating=!1;return}i||e?(this.#n=_(this.#n,i?-1:1,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#n]?.value,this.multiple||(this.selectedValues=[this.focusedValue]),this.isNavigating=!0):t?this.value=Di(this.multiple,this.selectedValues):this.multiple?this.focusedValue!==void 0&&(o.name==="tab"||this.isNavigating&&o.name==="space")?this.toggleSelected(this.focusedValue):this.isNavigating=!1:(this.focusedValue&&(this.selectedValues=[this.focusedValue]),this.isNavigating=!1)}deselectAll(){this.selectedValues=[]}toggleSelected(n){this.filteredOptions.length!==0&&(this.multiple?this.selectedValues.includes(n)?this.selectedValues=this.selectedValues.filter((o)=>o!==n):this.selectedValues=[...this.selectedValues,n]:this.selectedValues=[n])}#i(n){if(n!==this.#e){this.#e=n;let o=this.options;n&&this.#r?this.filteredOptions=o.filter((t)=>this.#r?.(n,t)):this.filteredOptions=[...o];let i=Li(this.focusedValue,this.filteredOptions);this.#n=_(i,0,this.filteredOptions);let e=this.filteredOptions[this.#n];e&&!e.disabled?this.focusedValue=e.value:this.focusedValue=void 0,this.multiple||(this.focusedValue!==void 0?this.toggleSelected(this.focusedValue):this.deselectAll())}}};class dn extends T{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(r){super(r,!1),this.value=!!r.initialValue,this.on("userInput",()=>{this.value=this._value}),this.on("confirm",(n)=>{this.output.write(W.cursor.move(0,-1)),this.value=n,this.state="submit",this.close()}),this.on("cursor",()=>{this.value=!this.value})}}var ji={Y:{type:"year",len:4},M:{type:"month",len:2},D:{type:"day",len:2}};function oo(r){return[...r].map((n)=>ji[n])}function Mi(r){let n=new Intl.DateTimeFormat(r,{year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(new Date(2000,0,15)),o=[],i="/";for(let e of n)e.type==="literal"?i=e.value.trim()||e.value:(e.type==="year"||e.type==="month"||e.type==="day")&&o.push({type:e.type,len:e.type==="year"?4:2});return{segments:o,separator:i}}function cn(r){return Number.parseInt((r||"0").replace(/_/g,"0"),10)||0}function Rr(r){return{year:cn(r.year),month:cn(r.month),day:cn(r.day)}}function mn(r,n){return new Date(r||2001,n||1,0).getDate()}function so(r){let{year:n,month:o,day:i}=Rr(r);if(!n||n<0||n>9999||!o||o<1||o>12||!i||i<1)return;let e=new Date(Date.UTC(n,o-1,i));if(!(e.getUTCFullYear()!==n||e.getUTCMonth()!==o-1||e.getUTCDate()!==i))return{year:n,month:o,day:i}}function io(r){let n=so(r);return n?new Date(Date.UTC(n.year,n.month-1,n.day)):void 0}function Ui(r,n,o,i){let e=o?{year:o.getUTCFullYear(),month:o.getUTCMonth()+1,day:o.getUTCDate()}:null,t=i?{year:i.getUTCFullYear(),month:i.getUTCMonth()+1,day:i.getUTCDate()}:null;return r==="year"?{min:e?.year??1,max:t?.year??9999}:r==="month"?{min:e&&n.year===e.year?e.month:1,max:t&&n.year===t.year?t.month:12}:{min:e&&n.year===e.year&&n.month===e.month?e.day:1,max:t&&n.year===t.year&&n.month===t.month?t.day:mn(n.year,n.month)}}class co extends T{#n;#e;#r;#t;#s;#o={segmentIndex:0,positionInSegment:0};#i=!0;#a=null;inlineError="";get segmentCursor(){return{...this.#o}}get segmentValues(){return{...this.#r}}get segments(){return this.#n}get separator(){return this.#e}get formattedValue(){return this.#u(this.#r)}#u(r){return this.#n.map((n)=>r[n.type]).join(this.#e)}#c(){this._setUserInput(this.#u(this.#r)),this._setValue(io(this.#r)??void 0)}constructor(r){let n=r.format?{segments:oo(r.format),separator:r.separator??"/"}:Mi(r.locale),o=r.separator??n.separator,i=r.format?oo(r.format):n.segments,e=r.initialValue??r.defaultValue,t=e?{year:String(e.getUTCFullYear()).padStart(4,"0"),month:String(e.getUTCMonth()+1).padStart(2,"0"),day:String(e.getUTCDate()).padStart(2,"0")}:{year:"____",month:"__",day:"__"},a=i.map((s)=>t[s.type]).join(o);super({...r,initialUserInput:a},!1),this.#n=i,this.#e=o,this.#r=t,this.#t=r.minDate,this.#s=r.maxDate,this.#c(),this.on("cursor",(s)=>this.#d(s)),this.on("key",(s,c)=>this.#g(s,c)),this.on("finalize",()=>this.#h(r))}#f(){let r=Math.max(0,Math.min(this.#o.segmentIndex,this.#n.length-1)),n=this.#n[r];if(n)return this.#o.positionInSegment=Math.max(0,Math.min(this.#o.positionInSegment,n.len-1)),{segment:n,index:r}}#m(r){this.inlineError="",this.#a=null;let n=this.#f();n&&(this.#o.segmentIndex=Math.max(0,Math.min(this.#n.length-1,n.index+r)),this.#o.positionInSegment=0,this.#i=!0)}#p(r){let n=this.#f();if(!n)return;let{segment:o}=n,i=this.#r[o.type],e=!i||i.replace(/_/g,"")==="",t=Number.parseInt((i||"0").replace(/_/g,"0"),10)||0,a=Ui(o.type,Rr(this.#r),this.#t,this.#s),s;e?s=r===1?a.min:a.max:s=Math.max(Math.min(a.max,t+r),a.min),this.#r={...this.#r,[o.type]:s.toString().padStart(o.len,"0")},this.#i=!0,this.#a=null,this.#c()}#d(r){if(r)switch(r){case"right":return this.#m(1);case"left":return this.#m(-1);case"up":return this.#p(1);case"down":return this.#p(-1)}}#g(r,n){if(n?.name==="backspace"||n?.sequence==="\x7F"||n?.sequence==="\b"||r==="\x7F"||r==="\b"){this.inlineError="";let o=this.#f();if(!o)return;if(!this.#r[o.segment.type].replace(/_/g,"")){this.#m(-1);return}this.#r[o.segment.type]="_".repeat(o.segment.len),this.#i=!0,this.#o.positionInSegment=0,this.#c();return}if(n?.name==="tab"){this.inlineError="";let o=this.#f();if(!o)return;let i=n.shift?-1:1,e=o.index+i;e>=0&&e<this.#n.length&&(this.#o.segmentIndex=e,this.#o.positionInSegment=0,this.#i=!0);return}if(r&&/^[0-9]$/.test(r)){let o=this.#f();if(!o)return;let{segment:i}=o,e=!this.#r[i.type].replace(/_/g,"");if(this.#i&&this.#a!==null&&!e){let u=this.#a+r,h={...this.#r,[i.type]:u},l=this.#l(h,i);if(l){this.inlineError=l,this.#a=null,this.#i=!1;return}this.inlineError="",this.#r[i.type]=u,this.#a=null,this.#i=!1,this.#c(),o.index<this.#n.length-1&&(this.#o.segmentIndex=o.index+1,this.#o.positionInSegment=0,this.#i=!0);return}this.#i&&!e&&(this.#r[i.type]="_".repeat(i.len),this.#o.positionInSegment=0),this.#i=!1,this.#a=null;let t=this.#r[i.type],a=t.indexOf("_"),s=a>=0?a:Math.min(this.#o.positionInSegment,i.len-1);if(s<0||s>=i.len)return;let c=t.slice(0,s)+r+t.slice(s+1),f=!1;if(s===0&&t==="__"&&(i.type==="month"||i.type==="day")){let u=Number.parseInt(r,10);c=`0${r}`,f=u<=(i.type==="month"?1:2)}if(i.type==="year"&&(c=(t.replace(/_/g,"")+r).padStart(i.len,"_")),!c.includes("_")){let u={...this.#r,[i.type]:c},h=this.#l(u,i);if(h){this.inlineError=h;return}}this.inlineError="",this.#r[i.type]=c;let d=c.includes("_")?void 0:so(this.#r);if(d){let{year:u,month:h}=d,l=mn(u,h);this.#r={year:String(Math.max(0,Math.min(9999,u))).padStart(4,"0"),month:String(Math.max(1,Math.min(12,h))).padStart(2,"0"),day:String(Math.max(1,Math.min(l,d.day))).padStart(2,"0")}}this.#c();let g=c.indexOf("_");f?(this.#i=!0,this.#a=r):g>=0?this.#o.positionInSegment=g:a>=0&&o.index<this.#n.length-1?(this.#o.segmentIndex=o.index+1,this.#o.positionInSegment=0,this.#i=!0):this.#o.positionInSegment=Math.min(s+1,i.len-1)}}#l(r,n){let{month:o,day:i}=Rr(r);if(n.type==="month"&&(o<0||o>12))return q.date.messages.invalidMonth;if(n.type==="day"&&(i<0||i>31))return q.date.messages.invalidDay(31,"any month")}#h(r){let{year:n,month:o,day:i}=Rr(this.#r);if(n&&o&&i){let e=mn(n,o);this.#r={...this.#r,day:String(Math.min(i,e)).padStart(2,"0")}}this.value=io(this.#r)??r.defaultValue??void 0}}var Hi=class extends T{options;cursor=0;#n;getGroupItems(n){return this.options.filter((o)=>o.group===n)}isGroupSelected(n){let o=this.getGroupItems(n),i=this.value;return i===void 0?!1:o.every((e)=>i.includes(e.value))}toggleValue(){let n=this.options[this.cursor];if(n!==void 0)if(this.value===void 0&&(this.value=[]),n.group===!0){let o=n.value,i=this.getGroupItems(o);this.isGroupSelected(o)?this.value=this.value.filter((e)=>i.findIndex((t)=>t.value===e)===-1):this.value=[...this.value,...i.map((e)=>e.value)],this.value=Array.from(new Set(this.value))}else{let o=this.value.includes(n.value);this.value=o?this.value.filter((i)=>i!==n.value):[...this.value,n.value]}}constructor(n){super(n,!1);let{options:o}=n;this.#n=n.selectableGroups!==!1,this.options=Object.entries(o).flatMap(([i,e])=>[{value:i,group:!0,label:i},...e.map((t)=>({...t,group:i}))]),this.value=[...n.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:i})=>i===n.cursorAt),this.#n?0:1),this.on("cursor",(i)=>{switch(i){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let e=this.options[this.cursor]?.group===!0;!this.#n&&e&&(this.cursor=this.cursor===0?this.options.length-1:this.cursor-1);break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let e=this.options[this.cursor]?.group===!0;!this.#n&&e&&(this.cursor=this.cursor===this.options.length-1?0:this.cursor+1);break}case"space":this.toggleValue();break}})}},Ei=new Set(["up","down","left","right"]);class fo extends T{#n=!1;#e;focused="editor";get userInputWithCursor(){if(this.state==="submit")return this.userInput;let r=this.userInput;if(this.cursor>=r.length)return`${r}\u2588`;let n=r.slice(0,this.cursor),o=r.slice(this.cursor,this.cursor+1),i=r.slice(this.cursor+1);return o===`
|
|
18
|
-
`?`${
|
|
19
|
-
${i}`:`${
|
|
20
|
-
`),this._cursor++,!1);let
|
|
21
|
-
`&&(this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--),!0):(this.#
|
|
22
|
-
`),this._cursor++,!1)}constructor(
|
|
23
|
-
`);
|
|
24
|
-
`:""}${
|
|
25
|
-
`,
|
|
26
|
-
${
|
|
27
|
-
${
|
|
28
|
-
`:` ${
|
|
29
|
-
${
|
|
30
|
-
`}}}}).prompt()};var
|
|
31
|
-
`).map((
|
|
32
|
-
`),
|
|
33
|
-
${
|
|
34
|
-
`:""}${
|
|
35
|
-
`,
|
|
36
|
-
${
|
|
37
|
-
`).map((
|
|
38
|
-
`),
|
|
39
|
-
`).length,
|
|
40
|
-
`).length+1;return`${
|
|
41
|
-
${
|
|
42
|
-
${
|
|
43
|
-
`}default:{let
|
|
44
|
-
`).length,
|
|
45
|
-
`),
|
|
46
|
-
${
|
|
47
|
-
${
|
|
48
|
-
`}}}}).prompt()};var
|
|
49
|
-
`);if(
|
|
3
|
+
var Ri=Object.create;var{getPrototypeOf:Si,defineProperty:Ze,getOwnPropertyNames:Ii}=Object;var Pi=Object.prototype.hasOwnProperty;function _i(t){return this[t]}var Ei,Ai,Qe=(t,e,r)=>{var i=t!=null&&typeof t==="object";if(i){var n=e?Ei??=new WeakMap:Ai??=new WeakMap,s=n.get(t);if(s)return s}r=t!=null?Ri(Si(t)):{};let o=e||!t||!t.__esModule?Ze(r,"default",{value:t,enumerable:!0}):r;if(t&&typeof t==="object"||typeof t==="function"){for(let a of Ii(t))if(!Pi.call(o,a))Ze(o,a,{get:_i.bind(t,a),enumerable:!0})}if(i)n.set(t,o);return o};var Ti=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ve=Ti(function(Ys,hr){var $e={to(t,e){if(!e)return`\x1B[${t+1}G`;return`\x1B[${e+1};${t+1}H`},move(t,e){let r="";if(t<0)r+=`\x1B[${-t}D`;else if(t>0)r+=`\x1B[${t}C`;if(e<0)r+=`\x1B[${-e}A`;else if(e>0)r+=`\x1B[${e}B`;return r},up:(t=1)=>`\x1B[${t}A`,down:(t=1)=>`\x1B[${t}B`,forward:(t=1)=>`\x1B[${t}C`,backward:(t=1)=>`\x1B[${t}D`,nextLine:(t=1)=>"\x1B[E".repeat(t),prevLine:(t=1)=>"\x1B[F".repeat(t),left:"\x1B[G",hide:"\x1B[?25l",show:"\x1B[?25h",save:"\x1B7",restore:"\x1B8"},Wi={up:(t=1)=>"\x1B[S".repeat(t),down:(t=1)=>"\x1B[T".repeat(t)},Ki={screen:"\x1B[2J",up:(t=1)=>"\x1B[1J".repeat(t),down:(t=1)=>"\x1B[J".repeat(t),line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",lines(t){let e="";for(let r=0;r<t;r++)e+=this.line+(r<t-1?$e.up():"");if(t)e+=$e.left;return e}};hr.exports={cursor:$e,scroll:Wi,erase:Ki,beep:"\x07"}});class q extends Error{constructor(t="Operation cancelled"){super(t)}}class v extends Error{hint;constructor(t,e){super(t);this.hint=e}}import{styleText as Nt}from"util";import{stdout as xe,stdin as $r}from"process";import*as rt from"readline";import qi from"readline";var tr=(()=>{let t=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return(e)=>{let r=0;t.lastIndex=0;while(t.test(e))r+=1;return e.length-r}})(),er=(t)=>t===12288||t>=65281&&t<=65376||t>=65504&&t<=65510,rr=(t)=>t===8987||t===9001||t>=12272&&t<=12287||t>=12289&&t<=12350||t>=12441&&t<=12543||t>=12549&&t<=12591||t>=12593&&t<=12686||t>=12688&&t<=12771||t>=12783&&t<=12830||t>=12832&&t<=12871||t>=12880&&t<=19903||t>=65040&&t<=65049||t>=65072&&t<=65106||t>=65108&&t<=65126||t>=65128&&t<=65131||t>=127488&&t<=127490||t>=127504&&t<=127547||t>=127552&&t<=127560||t>=131072&&t<=196605||t>=196608&&t<=262141;var Di=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,ki=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,ir=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,Li=/\t{1,1000}/y,nr=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu,Fi=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Ni=/\p{M}+/gu,Mi={limit:1/0,ellipsis:""},sr=(t,e={},r={})=>{let i=e.limit??1/0,n=e.ellipsis??"",s=e?.ellipsisWidth??(n?sr(n,Mi,r).width:0),o=0,a=r.controlWidth??0,u=r.tabWidth??8,l=r.emojiWidth??2,h=2,f=r.regularWidth??1,p=r.wideWidth??2,g=[[Fi,f],[Di,0],[ki,a],[Li,u],[nr,l],[ir,p]],d=0,y=0,R=t.length,E=0,C=!1,F=R,A=Math.max(0,i-s),x=0,L=0,T=0,P=0;t:while(!0){if(L>x||y>=R&&y>d){let k=t.slice(x,L)||t.slice(d,y);E=0;for(let z of k.replaceAll(Ni,"")){let G=z.codePointAt(0)||0;if(er(G))P=2;else if(rr(G))P=p;else P=f;if(T+P>A)F=Math.min(F,Math.max(x,d)+E);if(T+P>i){C=!0;break t}E+=z.length,T+=P}x=L=0}if(y>=R)break t;for(let k=0,z=g.length;k<z;k++){let[G,At]=g[k];if(G.lastIndex=y,G.test(t)){if(E=G===ir?tr(t.slice(y,G.lastIndex)):G===nr?1:G.lastIndex-y,P=E*At,T+P>A)F=Math.min(F,y+Math.floor((A-T)/At));if(T+P>i){C=!0;break t}T+=P,x=d,L=y,y=d=G.lastIndex;continue t}}y+=1}return{width:C?A:T,index:C?F:R,truncated:C,ellipsed:C&&i>=s}},or=sr;var Oi={limit:1/0,ellipsis:"",ellipsisWidth:0},Ui=(t,e={})=>or(t,Oi,e).width,H=Ui;var Dt="\x1B",pr="\x9B",Vi=39,ge="\x07",mr="[",Gi="]",dr="m",ye=`${Gi}8;;`,ar=new RegExp(`(?:\\${mr}(?<code>\\d+)m|\\${ye}(?<uri>.*)${ge})`,"y"),ur=(t)=>{if(t>=30&&t<=37)return 39;if(t>=90&&t<=97)return 39;if(t>=40&&t<=47)return 49;if(t>=100&&t<=107)return 49;if(t===1||t===2)return 22;if(t===3)return 23;if(t===4)return 24;if(t===7)return 27;if(t===8)return 28;if(t===9)return 29;if(t===0)return 0;return},lr=(t)=>`${Dt}${mr}${t}${dr}`,cr=(t)=>`${Dt}${ye}${t}${ge}`,fe=(t,e,r)=>{let i=e[Symbol.iterator](),n=!1,s=!1,o=t.at(-1),a=o===void 0?0:H(o),u=i.next(),l=i.next(),h=0;while(!u.done){let f=u.value,p=H(f);if(a+p<=r)t[t.length-1]+=f;else t.push(f),a=0;if(f===Dt||f===pr)n=!0,s=e.startsWith(ye,h+1);if(n){if(s){if(f===ge)n=!1,s=!1}else if(f===dr)n=!1}else if(a+=p,a===r&&!l.done)t.push(""),a=0;u=l,l=i.next(),h+=f.length}if(o=t.at(-1),!a&&o!==void 0&&o.length&&t.length>1)t[t.length-2]+=t.pop()},Hi=(t)=>{let e=t.split(" "),r=e.length;while(r){if(H(e[r-1]))break;r--}if(r===e.length)return t;return e.slice(0,r).join(" ")+e.slice(r).join("")},Bi=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let i="",n,s,o=t.split(" "),a=[""],u=0;for(let f=0;f<o.length;f++){let p=o[f];if(r.trim!==!1){let d=a.at(-1)??"",y=d.trimStart();if(d.length!==y.length)a[a.length-1]=y,u=H(y)}if(f!==0){if(u>=e&&(r.wordWrap===!1||r.trim===!1))a.push(""),u=0;if(u||r.trim===!1)a[a.length-1]+=" ",u++}let g=H(p);if(r.hard&&g>e){let d=e-u,y=1+Math.floor((g-d-1)/e);if(Math.floor((g-1)/e)<y)a.push("");fe(a,p,e),u=H(a.at(-1)??"");continue}if(u+g>e&&u&&g){if(r.wordWrap===!1&&u<e){fe(a,p,e),u=H(a.at(-1)??"");continue}a.push(""),u=0}if(u+g>e&&r.wordWrap===!1){fe(a,p,e),u=H(a.at(-1)??"");continue}a[a.length-1]+=p,u+=g}if(r.trim!==!1)a=a.map((f)=>Hi(f));let l=a.join(`
|
|
4
|
+
`),h=!1;for(let f=0;f<l.length;f++){let p=l[f];if(i+=p,!h){if(h=p>="\uD800"&&p<="\uDBFF",h)continue}else h=!1;if(p===Dt||p===pr){ar.lastIndex=f+1;let d=ar.exec(l)?.groups;if(d?.code!==void 0){let y=Number.parseFloat(d.code);n=y===Vi?void 0:y}else if(d?.uri!==void 0)s=d.uri.length===0?void 0:d.uri}if(l[f+1]===`
|
|
5
|
+
`){if(s)i+=cr("");let g=n?ur(n):void 0;if(n&&g)i+=lr(g)}else if(p===`
|
|
6
|
+
`){if(n&&ur(n))i+=lr(n);if(s)i+=cr(s)}}return i},ji=/\r?\n/;function Y(t,e,r){return String(t).normalize().split(ji).map((i)=>Bi(i,e,r)).join(`
|
|
7
|
+
`)}var U=Qe(ve(),1);import{ReadStream as fr}from"tty";function Z(t,e,r){if(!r.some((o)=>!o.disabled))return t;let i=t+e,n=Math.max(r.length-1,0),s=i<0?n:i>n?0:i;return r[s]?.disabled?Z(s,e<0?-1:1,r):s}function kt(t,e,r,i){let n=i.split(`
|
|
8
|
+
`),s=0,o=t;for(let u of n){if(o<=u.length)break;o-=u.length+1,s++}for(s=Math.max(0,Math.min(n.length-1,s+r)),o=Math.min(o,n[s].length)+e;o<0&&s>0;)s--,o+=n[s].length+1;for(;o>n[s].length&&s<n.length-1;)o-=n[s].length+1,s++;o=Math.max(0,Math.min(n[s].length,o));let a=0;for(let u=0;u<s;u++)a+=n[u].length+1;return a+o}var zi=["up","down","left","right","space","enter","cancel"],Yi=["January","February","March","April","May","June","July","August","September","October","November","December"],N={actions:new Set(zi),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"},withGuide:!0,date:{monthNames:[...Yi],messages:{required:"Please enter a valid date",invalidMonth:"There are only 12 months in a year",invalidDay:(t,e)=>`There are only ${t} days in ${e}`,afterMin:(t)=>`Date must be on or after ${t.toISOString().slice(0,10)}`,beforeMax:(t)=>`Date must be on or before ${t.toISOString().slice(0,10)}`}}};function Re(t,e){if(typeof t=="string")return N.aliases.get(t)===e;for(let r of t)if(r!==void 0&&Re(r,e))return!0;return!1}function Ji(t,e){if(t===e)return;let r=t.split(`
|
|
9
|
+
`),i=e.split(`
|
|
10
|
+
`),n=Math.max(r.length,i.length),s=[];for(let o=0;o<n;o++)r[o]!==i[o]&&s.push(o);return{lines:s,numLinesBefore:r.length,numLinesAfter:i.length,numLines:n}}var Xi=globalThis.process.platform.startsWith("win"),we=Symbol("clack:cancel");function $t(t){return t===we}function Lt(t,e){let r=t;r.isTTY&&r.setRawMode(e)}function vr({input:t=$r,output:e=xe,overwrite:r=!0,hideCursor:i=!0}={}){let n=rt.createInterface({input:t,output:e,prompt:"",tabSize:1});rt.emitKeypressEvents(t,n),t instanceof fr&&t.isTTY&&t.setRawMode(!0);let s=(o,{name:a,sequence:u})=>{let l=String(o);if(Re([l,a,u],"cancel")){i&&e.write(U.cursor.show),process.exit(0);return}if(!r)return;rt.moveCursor(e,a==="return"?0:-1,a==="return"?-1:0,()=>{rt.clearLine(e,1,()=>{t.once("keypress",s)})})};return i&&e.write(U.cursor.hide),t.once("keypress",s),()=>{t.off("keypress",s),i&&e.write(U.cursor.show),t instanceof fr&&t.isTTY&&!Xi&&t.setRawMode(!1),n.terminal=!1,n.close()}}var vt=(t)=>("columns"in t)&&typeof t.columns=="number"?t.columns:80,Se=(t)=>("rows"in t)&&typeof t.rows=="number"?t.rows:20;function it(t,e,r,i=r,n=r,s){let o=vt(t??xe);return Y(e,o-r.length,{hard:!0,trim:!1}).split(`
|
|
11
|
+
`).map((a,u,l)=>{let h=s?s(a,u):a;return u===0?`${i}${h}`:u===l.length-1?`${n}${h}`:`${r}${h}`}).join(`
|
|
12
|
+
`)}function br(t,e){if("~standard"in t){let r=t["~standard"].validate(e);if(r instanceof Promise)throw TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");return r.issues?.at(0)?.message}return t(e)}class Q{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame="";_subscribers=new Map;_cursor=0;state="initial";error="";value;userInput="";constructor(t,e=!0){let{input:r=$r,output:i=xe,render:n,signal:s,...o}=t;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=e,this._abortSignal=s,this.input=r,this.output=i}unsubscribe(){this._subscribers.clear()}setSubscriber(t,e){let r=this._subscribers.get(t)??[];r.push(e),this._subscribers.set(t,r)}on(t,e){this.setSubscriber(t,{cb:e})}once(t,e){this.setSubscriber(t,{cb:e,once:!0})}emit(t,...e){let r=this._subscribers.get(t)??[],i=[];for(let n of r)n.cb(...e),n.once&&i.push(()=>r.splice(r.indexOf(n),1));for(let n of i)n()}prompt(){return new Promise((t)=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),t(we);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}this.rl=qi.createInterface({input:this.input,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on("keypress",this.onKeypress),Lt(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(U.cursor.show),this.output.off("resize",this.render),Lt(this.input,!1),t(this.value)}),this.once("cancel",()=>{this.output.write(U.cursor.show),this.output.off("resize",this.render),Lt(this.input,!1),t(we)})})}_isActionKey(t,e){return t==="\t"}_shouldSubmit(t,e){return!0}_setValue(t){this.value=t,this.emit("value",this.value)}_setUserInput(t,e){this.userInput=t??"",this.emit("userInput",this.userInput),e&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:"u"}),this._setUserInput("")}onKeypress(t,e){if(this._track&&e.name!=="return"&&(e.name&&this._isActionKey(t,e)&&this.rl?.write(null,{ctrl:!0,name:"h"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state==="error"&&(this.state="active"),e?.name&&(!this._track&&N.aliases.has(e.name)&&this.emit("cursor",N.aliases.get(e.name)),N.actions.has(e.name)&&this.emit("cursor",e.name)),t&&(t.toLowerCase()==="y"||t.toLowerCase()==="n")&&this.emit("confirm",t.toLowerCase()==="y"),this.emit("key",t,e),e?.name==="return"&&this._shouldSubmit(t,e)){if(this.opts.validate){let r=br(this.opts.validate,this.value);r&&(this.error=r instanceof Error?r.message:r,this.state="error",this.rl?.write(this.userInput))}this.state!=="error"&&(this.state="submit")}Re([t,e?.name,e?.sequence],"cancel")&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close()}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
|
|
13
|
+
`),Lt(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let t=Y(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`
|
|
14
|
+
`).length-1;this.output.write(U.cursor.move(-999,t*-1))}render(){let t=Y(this._render(this)??"",process.stdout.columns,{hard:!0,trim:!1});if(t!==this._prevFrame){if(this.state==="initial")this.output.write(U.cursor.hide);else{let e=Ji(this._prevFrame,t),r=Se(this.output);if(this.restoreCursor(),e){let i=Math.max(0,e.numLinesAfter-r),n=Math.max(0,e.numLinesBefore-r),s=e.lines.find((o)=>o>=i);if(s===void 0){this._prevFrame=t;return}if(e.lines.length===1){this.output.write(U.cursor.move(0,s-n)),this.output.write(U.erase.lines(1));let o=t.split(`
|
|
15
|
+
`);this.output.write(o[s]),this._prevFrame=t,this.output.write(U.cursor.move(0,o.length-s-1));return}else if(e.lines.length>1){if(i<n)s=i;else{let a=s-n;a>0&&this.output.write(U.cursor.move(0,a))}this.output.write(U.erase.down());let o=t.split(`
|
|
16
|
+
`).slice(s);this.output.write(o.join(`
|
|
17
|
+
`)),this._prevFrame=t;return}}this.output.write(U.erase.down())}this.output.write(t),this.state==="initial"&&(this.state="active"),this._prevFrame=t}}}function Zi(t,e){if(t===void 0||e.length===0)return 0;let r=e.findIndex((i)=>i.value===t);return r!==-1?r:0}function Qi(t,e){return(e.label??String(e.value)).toLowerCase().includes(t.toLowerCase())}function tn(t,e){if(e)return t?e:e[0]}var en=class extends Q{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#e=0;#n="";#t;#s;#a;get cursor(){return this.#e}get userInputWithCursor(){if(!this.userInput)return Nt(["inverse","hidden"],"_");if(this._cursor>=this.userInput.length)return`${this.userInput}\u2588`;let e=this.userInput.slice(0,this.cursor),r=this.userInput.slice(this.cursor,this.cursor+1),i=this.userInput.slice(this.cursor+1);return`${e}${Nt("inverse",r)}${i}`}get options(){return typeof this.#s=="function"?this.#s():this.#s}constructor(e){super(e),this.#s=e.options,this.#a=e.placeholder;let r=this.options;this.filteredOptions=[...r],this.multiple=e.multiple===!0,this.#t=typeof e.options=="function"?e.filter:e.filter??Qi;let i;if(e.initialValue&&Array.isArray(e.initialValue)?this.multiple?i=e.initialValue:i=e.initialValue.slice(0,1):!this.multiple&&this.options.length>0&&(i=[this.options[0]?.value]),i)for(let n of i){let s=r.findIndex((o)=>o.value===n);s!==-1&&(this.toggleSelected(n),this.#e=s)}this.focusedValue=this.options[this.#e]?.value,this.on("key",(n,s)=>this.#r(n,s)),this.on("userInput",(n)=>this.#i(n))}_isActionKey(e,r){return e==="\t"||this.multiple&&this.isNavigating&&r.name==="space"&&e!==void 0&&e!==""}#r(e,r){let i=r.name==="up",n=r.name==="down",s=r.name==="return",o=this.userInput===""||this.userInput==="\t",a=this.#a,u=this.options,l=a!==void 0&&a!==""&&u.some((h)=>!h.disabled&&(this.#t?this.#t(a,h):!0));if(r.name==="tab"&&o&&l){this.userInput==="\t"&&this._clearUserInput(),this._setUserInput(a,!0),this.isNavigating=!1;return}i||n?(this.#e=Z(this.#e,i?-1:1,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#e]?.value,this.multiple||(this.selectedValues=[this.focusedValue]),this.isNavigating=!0):s?this.value=tn(this.multiple,this.selectedValues):this.multiple?this.focusedValue!==void 0&&(r.name==="tab"||this.isNavigating&&r.name==="space")?this.toggleSelected(this.focusedValue):this.isNavigating=!1:(this.focusedValue&&(this.selectedValues=[this.focusedValue]),this.isNavigating=!1)}deselectAll(){this.selectedValues=[]}toggleSelected(e){this.filteredOptions.length!==0&&(this.multiple?this.selectedValues.includes(e)?this.selectedValues=this.selectedValues.filter((r)=>r!==e):this.selectedValues=[...this.selectedValues,e]:this.selectedValues=[e])}#i(e){if(e!==this.#n){this.#n=e;let r=this.options;e&&this.#t?this.filteredOptions=r.filter((s)=>this.#t?.(e,s)):this.filteredOptions=[...r];let i=Zi(this.focusedValue,this.filteredOptions);this.#e=Z(i,0,this.filteredOptions);let n=this.filteredOptions[this.#e];n&&!n.disabled?this.focusedValue=n.value:this.focusedValue=void 0,this.multiple||(this.focusedValue!==void 0?this.toggleSelected(this.focusedValue):this.deselectAll())}}};class Ie extends Q{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(t){super(t,!1),this.value=!!t.initialValue,this.on("userInput",()=>{this.value=this._value}),this.on("confirm",(e)=>{this.output.write(U.cursor.move(0,-1)),this.value=e,this.state="submit",this.close()}),this.on("cursor",()=>{this.value=!this.value})}}var rn={Y:{type:"year",len:4},M:{type:"month",len:2},D:{type:"day",len:2}};function gr(t){return[...t].map((e)=>rn[e])}function nn(t){let e=new Intl.DateTimeFormat(t,{year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(new Date(2000,0,15)),r=[],i="/";for(let n of e)n.type==="literal"?i=n.value.trim()||n.value:(n.type==="year"||n.type==="month"||n.type==="day")&&r.push({type:n.type,len:n.type==="year"?4:2});return{segments:r,separator:i}}function be(t){return Number.parseInt((t||"0").replace(/_/g,"0"),10)||0}function Ft(t){return{year:be(t.year),month:be(t.month),day:be(t.day)}}function Ce(t,e){return new Date(t||2001,e||1,0).getDate()}function wr(t){let{year:e,month:r,day:i}=Ft(t);if(!e||e<0||e>9999||!r||r<1||r>12||!i||i<1)return;let n=new Date(Date.UTC(e,r-1,i));if(!(n.getUTCFullYear()!==e||n.getUTCMonth()!==r-1||n.getUTCDate()!==i))return{year:e,month:r,day:i}}function yr(t){let e=wr(t);return e?new Date(Date.UTC(e.year,e.month-1,e.day)):void 0}function sn(t,e,r,i){let n=r?{year:r.getUTCFullYear(),month:r.getUTCMonth()+1,day:r.getUTCDate()}:null,s=i?{year:i.getUTCFullYear(),month:i.getUTCMonth()+1,day:i.getUTCDate()}:null;return t==="year"?{min:n?.year??1,max:s?.year??9999}:t==="month"?{min:n&&e.year===n.year?n.month:1,max:s&&e.year===s.year?s.month:12}:{min:n&&e.year===n.year&&e.month===n.month?n.day:1,max:s&&e.year===s.year&&e.month===s.month?s.day:Ce(e.year,e.month)}}class Cr extends Q{#e;#n;#t;#s;#a;#r={segmentIndex:0,positionInSegment:0};#i=!0;#o=null;inlineError="";get segmentCursor(){return{...this.#r}}get segmentValues(){return{...this.#t}}get segments(){return this.#e}get separator(){return this.#n}get formattedValue(){return this.#p(this.#t)}#p(t){return this.#e.map((e)=>t[e.type]).join(this.#n)}#u(){this._setUserInput(this.#p(this.#t)),this._setValue(yr(this.#t)??void 0)}constructor(t){let e=t.format?{segments:gr(t.format),separator:t.separator??"/"}:nn(t.locale),r=t.separator??e.separator,i=t.format?gr(t.format):e.segments,n=t.initialValue??t.defaultValue,s=n?{year:String(n.getUTCFullYear()).padStart(4,"0"),month:String(n.getUTCMonth()+1).padStart(2,"0"),day:String(n.getUTCDate()).padStart(2,"0")}:{year:"____",month:"__",day:"__"},o=i.map((a)=>s[a.type]).join(r);super({...t,initialUserInput:o},!1),this.#e=i,this.#n=r,this.#t=s,this.#s=t.minDate,this.#a=t.maxDate,this.#u(),this.on("cursor",(a)=>this.#h(a)),this.on("key",(a,u)=>this.#f(a,u)),this.on("finalize",()=>this.#g(t))}#l(){let t=Math.max(0,Math.min(this.#r.segmentIndex,this.#e.length-1)),e=this.#e[t];if(e)return this.#r.positionInSegment=Math.max(0,Math.min(this.#r.positionInSegment,e.len-1)),{segment:e,index:t}}#c(t){this.inlineError="",this.#o=null;let e=this.#l();e&&(this.#r.segmentIndex=Math.max(0,Math.min(this.#e.length-1,e.index+t)),this.#r.positionInSegment=0,this.#i=!0)}#m(t){let e=this.#l();if(!e)return;let{segment:r}=e,i=this.#t[r.type],n=!i||i.replace(/_/g,"")==="",s=Number.parseInt((i||"0").replace(/_/g,"0"),10)||0,o=sn(r.type,Ft(this.#t),this.#s,this.#a),a;n?a=t===1?o.min:o.max:a=Math.max(Math.min(o.max,s+t),o.min),this.#t={...this.#t,[r.type]:a.toString().padStart(r.len,"0")},this.#i=!0,this.#o=null,this.#u()}#h(t){if(t)switch(t){case"right":return this.#c(1);case"left":return this.#c(-1);case"up":return this.#m(1);case"down":return this.#m(-1)}}#f(t,e){if(e?.name==="backspace"||e?.sequence==="\x7F"||e?.sequence==="\b"||t==="\x7F"||t==="\b"){this.inlineError="";let r=this.#l();if(!r)return;if(!this.#t[r.segment.type].replace(/_/g,"")){this.#c(-1);return}this.#t[r.segment.type]="_".repeat(r.segment.len),this.#i=!0,this.#r.positionInSegment=0,this.#u();return}if(e?.name==="tab"){this.inlineError="";let r=this.#l();if(!r)return;let i=e.shift?-1:1,n=r.index+i;n>=0&&n<this.#e.length&&(this.#r.segmentIndex=n,this.#r.positionInSegment=0,this.#i=!0);return}if(t&&/^[0-9]$/.test(t)){let r=this.#l();if(!r)return;let{segment:i}=r,n=!this.#t[i.type].replace(/_/g,"");if(this.#i&&this.#o!==null&&!n){let p=this.#o+t,g={...this.#t,[i.type]:p},d=this.#d(g,i);if(d){this.inlineError=d,this.#o=null,this.#i=!1;return}this.inlineError="",this.#t[i.type]=p,this.#o=null,this.#i=!1,this.#u(),r.index<this.#e.length-1&&(this.#r.segmentIndex=r.index+1,this.#r.positionInSegment=0,this.#i=!0);return}this.#i&&!n&&(this.#t[i.type]="_".repeat(i.len),this.#r.positionInSegment=0),this.#i=!1,this.#o=null;let s=this.#t[i.type],o=s.indexOf("_"),a=o>=0?o:Math.min(this.#r.positionInSegment,i.len-1);if(a<0||a>=i.len)return;let u=s.slice(0,a)+t+s.slice(a+1),l=!1;if(a===0&&s==="__"&&(i.type==="month"||i.type==="day")){let p=Number.parseInt(t,10);u=`0${t}`,l=p<=(i.type==="month"?1:2)}if(i.type==="year"&&(u=(s.replace(/_/g,"")+t).padStart(i.len,"_")),!u.includes("_")){let p={...this.#t,[i.type]:u},g=this.#d(p,i);if(g){this.inlineError=g;return}}this.inlineError="",this.#t[i.type]=u;let h=u.includes("_")?void 0:wr(this.#t);if(h){let{year:p,month:g}=h,d=Ce(p,g);this.#t={year:String(Math.max(0,Math.min(9999,p))).padStart(4,"0"),month:String(Math.max(1,Math.min(12,g))).padStart(2,"0"),day:String(Math.max(1,Math.min(d,h.day))).padStart(2,"0")}}this.#u();let f=u.indexOf("_");l?(this.#i=!0,this.#o=t):f>=0?this.#r.positionInSegment=f:o>=0&&r.index<this.#e.length-1?(this.#r.segmentIndex=r.index+1,this.#r.positionInSegment=0,this.#i=!0):this.#r.positionInSegment=Math.min(a+1,i.len-1)}}#d(t,e){let{month:r,day:i}=Ft(t);if(e.type==="month"&&(r<0||r>12))return N.date.messages.invalidMonth;if(e.type==="day"&&(i<0||i>31))return N.date.messages.invalidDay(31,"any month")}#g(t){let{year:e,month:r,day:i}=Ft(this.#t);if(e&&r&&i){let n=Ce(e,r);this.#t={...this.#t,day:String(Math.min(i,n)).padStart(2,"0")}}this.value=yr(this.#t)??t.defaultValue??void 0}}var on=class extends Q{options;cursor=0;#e;getGroupItems(e){return this.options.filter((r)=>r.group===e)}isGroupSelected(e){let r=this.getGroupItems(e),i=this.value;return i===void 0?!1:r.every((n)=>i.includes(n.value))}toggleValue(){let e=this.options[this.cursor];if(e!==void 0)if(this.value===void 0&&(this.value=[]),e.group===!0){let r=e.value,i=this.getGroupItems(r);this.isGroupSelected(r)?this.value=this.value.filter((n)=>i.findIndex((s)=>s.value===n)===-1):this.value=[...this.value,...i.map((n)=>n.value)],this.value=Array.from(new Set(this.value))}else{let r=this.value.includes(e.value);this.value=r?this.value.filter((i)=>i!==e.value):[...this.value,e.value]}}constructor(e){super(e,!1);let{options:r}=e;this.#e=e.selectableGroups!==!1,this.options=Object.entries(r).flatMap(([i,n])=>[{value:i,group:!0,label:i},...n.map((s)=>({...s,group:i}))]),this.value=[...e.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:i})=>i===e.cursorAt),this.#e?0:1),this.on("cursor",(i)=>{switch(i){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let n=this.options[this.cursor]?.group===!0;!this.#e&&n&&(this.cursor=this.cursor===0?this.options.length-1:this.cursor-1);break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let n=this.options[this.cursor]?.group===!0;!this.#e&&n&&(this.cursor=this.cursor===this.options.length-1?0:this.cursor+1);break}case"space":this.toggleValue();break}})}},an=new Set(["up","down","left","right"]);class xr extends Q{#e=!1;#n;focused="editor";get userInputWithCursor(){if(this.state==="submit")return this.userInput;let t=this.userInput;if(this.cursor>=t.length)return`${t}\u2588`;let e=t.slice(0,this.cursor),r=t.slice(this.cursor,this.cursor+1),i=t.slice(this.cursor+1);return r===`
|
|
18
|
+
`?`${e}\u2588
|
|
19
|
+
${i}`:`${e}${Nt("inverse",r)}${i}`}get cursor(){return this._cursor}#t(t){if(this.userInput.length===0){this._setUserInput(t);return}this._setUserInput(this.userInput.slice(0,this.cursor)+t+this.userInput.slice(this.cursor))}#s(t){let e=this.value??"";switch(t){case"up":this._cursor=kt(this._cursor,0,-1,e);return;case"down":this._cursor=kt(this._cursor,0,1,e);return;case"left":this._cursor=kt(this._cursor,-1,0,e);return;case"right":this._cursor=kt(this._cursor,1,0,e);return}}_shouldSubmit(t,e){if(this.#n)return this.focused==="submit"?!0:(this.#t(`
|
|
20
|
+
`),this._cursor++,!1);let r=this.#e;return this.#e=!0,r&&this.cursor===this.userInput.length?(this.userInput[this.cursor-1]===`
|
|
21
|
+
`&&(this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--),!0):(this.#t(`
|
|
22
|
+
`),this._cursor++,!1)}constructor(t){let e=t.initialUserInput??t.initialValue;super({...t,initialUserInput:e},!1),e!==void 0&&(this._cursor=e.length),this.#n=t.showSubmit??!1,this.on("key",(r,i)=>{if(i?.name&&an.has(i.name)){this.#e=!1,this.#s(i.name);return}if(r==="\t"&&this.#n){this.focused=this.focused==="editor"?"submit":"editor";return}if(i?.name!=="return"){if(this.#e=!1,i?.name==="backspace"&&this.cursor>0){this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--;return}if(i?.name==="delete"&&this.cursor<this.userInput.length){this._setUserInput(this.userInput.slice(0,this.cursor)+this.userInput.slice(this.cursor+1));return}r&&(this.#n&&this.focused==="submit"&&(this.focused="editor"),this.#t(r??""),this._cursor++)}}),this.on("userInput",(r)=>{this._setValue(r)}),this.on("finalize",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value="")})}}class Pe extends Q{options;cursor=0;get _value(){return this.options[this.cursor]?.value}get _enabledOptions(){return this.options.filter((t)=>t.disabled!==!0)}toggleAll(){let t=this._enabledOptions,e=this.value!==void 0&&this.value.length===t.length;this.value=e?[]:t.map((r)=>r.value)}toggleInvert(){let t=this.value;if(!t)return;let e=this._enabledOptions.filter((r)=>!t.includes(r.value));this.value=e.map((r)=>r.value)}toggleValue(){this.value===void 0&&(this.value=[]);let t=this.value.includes(this._value);this.value=t?this.value.filter((e)=>e!==this._value):[...this.value,this._value]}constructor(t){super(t,!1),this.options=t.options,this.value=[...t.initialValues??[]];let e=Math.max(this.options.findIndex(({value:r})=>r===t.cursorAt),0);this.cursor=this.options[e]?.disabled?Z(e,1,this.options):e,this.on("key",(r,i)=>{i.name==="a"&&this.toggleAll(),i.name==="i"&&this.toggleInvert()}),this.on("cursor",(r)=>{switch(r){case"left":case"up":this.cursor=Z(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=Z(this.cursor,1,this.options);break;case"space":this.toggleValue();break}})}}var Rr=class extends Q{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){let e=this._selectedValue;this.value=e===void 0?void 0:e.value}constructor(e){super(e,!1),this.options=e.options;let r=this.options.findIndex(({value:n})=>n===e.initialValue),i=r===-1?0:r;this.cursor=this.options[i]?.disabled?Z(i,1,this.options):i,this.changeValue(),this.on("cursor",(n)=>{switch(n){case"left":case"up":this.cursor=Z(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=Z(this.cursor,1,this.options);break}this.changeValue()})}};class _e extends Q{get userInputWithCursor(){if(this.state==="submit")return this.userInput;let t=this.userInput;if(this.cursor>=t.length)return`${this.userInput}\u2588`;let e=t.slice(0,this.cursor),r=t.slice(this.cursor,this.cursor+1),i=t.slice(this.cursor+1);return`${e}${Nt("inverse",r)}${i}`}get cursor(){return this._cursor}constructor(t){super({...t,initialUserInput:t.initialUserInput??t.initialValue}),this.on("userInput",(e)=>{this._setValue(e)}),this.on("finalize",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value="")})}}import{styleText as c,stripVTControlCharacters as ao}from"util";import W from"process";var wt=Qe(ve(),1);function un(){if(W.platform!=="win32")return W.env.TERM!=="linux";return Boolean(W.env.CI)||Boolean(W.env.WT_SESSION)||Boolean(W.env.TERMINUS_SUBLIME)||W.env.ConEmuTask==="{cmd::Cmder}"||W.env.TERM_PROGRAM==="Terminus-Sublime"||W.env.TERM_PROGRAM==="vscode"||W.env.TERM==="xterm-256color"||W.env.TERM==="alacritty"||W.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var Ee=un(),ln=()=>process.env.CI==="true";var S=(t,e)=>Ee?t:e,cn=S("\u25C6","*"),Er=S("\u25A0","x"),Ar=S("\u25B2","x"),Ut=S("\u25C7","o"),pn=S("\u250C","T"),w=S("\u2502","|"),nt=S("\u2514","\u2014"),po=S("\u2510","T"),mo=S("\u2518","\u2014"),Ae=S("\u25CF",">"),Ot=S("\u25CB"," "),mn=S("\u25FB","[\u2022]"),Sr=S("\u25FC","[+]"),Ir=S("\u25FB","[ ]"),ho=S("\u25AA","\u2022"),Pr=S("\u2500","-"),dn=S("\u256E","+"),hn=S("\u251C","+"),fn=S("\u256F","+"),gn=S("\u2570","+"),fo=S("\u256D","+"),yn=S("\u25CF","\u2022"),$n=S("\u25C6","*"),vn=S("\u25B2","!"),bn=S("\u25A0","x"),Vt=(t)=>{switch(t){case"initial":case"active":return c("cyan",cn);case"cancel":return c("red",Er);case"error":return c("yellow",Ar);case"submit":return c("green",Ut)}},Tr=(t)=>{switch(t){case"initial":case"active":return c("cyan",w);case"cancel":return c("red",w);case"error":return c("yellow",w);case"submit":return c("green",w)}};function Dr(t,e){let r=[`${e?`${c("cyan",w)} `:""}${t.join(" \u2022 ")}`];return e&&r.push(c("cyan",nt)),r}var _r=(t,e,r,i,n,s=!1)=>{let o=e,a=0;if(s)for(let u=i-1;u>=r;u--){let l=t[u];if(l&&(o-=l.length),a++,o<=n)break}else for(let u=r;u<i;u++){let l=t[u];if(l&&(o-=l.length),a++,o<=n)break}return{lineCount:o,removals:a}},Te=({cursor:t,options:e,style:r,output:i=process.stdout,maxItems:n=Number.POSITIVE_INFINITY,columnPadding:s=0,rowPadding:o=4})=>{let a=vt(i)-s,u=Se(i),l=c("dim","..."),h=Math.max(u-o,0),f=Math.max(Math.min(n,h),5),p=0;t>=f-3&&(p=Math.max(Math.min(t-f+3,e.length-f),0));let g=f<e.length&&p>0,d=f<e.length&&p+f<e.length,y=Math.min(p+f,e.length),R=[],E=0;g&&E++,d&&E++;let C=p+(g?1:0),F=y-(d?1:0);for(let x=C;x<F;x++){let L=e[x],T=L?r(L,x===t):"",P=Y(T,a,{hard:!0,trim:!1}).split(`
|
|
23
|
+
`);R.push(P),E+=P.length}if(E>h){let x=0,L=0,T=E,P=t-C,k=h,z=()=>_r(R,T,0,P,k),G=()=>_r(R,T,P+1,R.length,k,!0);g?({lineCount:T,removals:x}=z(),T>k&&(d||(k-=1),{lineCount:T,removals:L}=G())):(d||(k-=1),{lineCount:T,removals:L}=G(),T>k&&(k-=1,{lineCount:T,removals:x}=z())),x>0&&(g=!0,R.splice(0,x)),L>0&&(d=!0,R.splice(R.length-L,L))}let A=[];g&&A.push(l);for(let x of R)for(let L of x)A.push(L);return d&&A.push(l),A};var kr=(t)=>{let e=t.active??"Yes",r=t.inactive??"No";return new Ie({active:e,inactive:r,signal:t.signal,input:t.input,output:t.output,initialValue:t.initialValue??!0,render(){let i=t.withGuide??N.withGuide,n=`${Vt(this.state)} `,s=i?`${c("gray",w)} `:"",o=it(t.output,t.message,s,n),a=`${i?`${c("gray",w)}
|
|
24
|
+
`:""}${o}
|
|
25
|
+
`,u=this.value?e:r;switch(this.state){case"submit":{let l=i?`${c("gray",w)} `:"";return`${a}${l}${c("dim",u)}`}case"cancel":{let l=i?`${c("gray",w)} `:"";return`${a}${l}${c(["strikethrough","dim"],u)}${i?`
|
|
26
|
+
${c("gray",w)}`:""}`}default:{let l=i?`${c("cyan",w)} `:"",h=i?c("cyan",nt):"";return`${a}${l}${this.value?`${c("green",Ae)} ${e}`:`${c("dim",Ot)} ${c("dim",e)}`}${t.vertical?i?`
|
|
27
|
+
${c("cyan",w)} `:`
|
|
28
|
+
`:` ${c("dim","/")} `}${this.value?`${c("dim",Ot)} ${c("dim",r)}`:`${c("green",Ae)} ${r}`}
|
|
29
|
+
${h}
|
|
30
|
+
`}}}}).prompt()};var Gt=async(t,e)=>{let r={},i=Object.keys(t);for(let n of i){let s=t[n],o=await s({results:r})?.catch((a)=>{throw a});if(typeof e?.onCancel=="function"&&$t(o)){r[n]="canceled",e.onCancel({results:r});continue}r[n]=o}return r},wn=[`${c("dim","\u2191/\u2193")} to navigate`,`${c("dim","Space:")} select`,`${c("dim","Enter:")} confirm`],bt=(t,e)=>t.split(`
|
|
31
|
+
`).map((r)=>e(r)).join(`
|
|
32
|
+
`),Lr=(t)=>{let e=(n,s)=>{let o=n.label??String(n.value);return s==="disabled"?`${c("gray",Ir)} ${bt(o,(a)=>c(["strikethrough","gray"],a))}${n.hint?` ${c("dim",`(${n.hint??"disabled"})`)}`:""}`:s==="active"?`${c("cyan",mn)} ${o}${n.hint?` ${c("dim",`(${n.hint})`)}`:""}`:s==="selected"?`${c("green",Sr)} ${bt(o,(a)=>c("dim",a))}${n.hint?` ${c("dim",`(${n.hint})`)}`:""}`:s==="cancelled"?`${bt(o,(a)=>c(["strikethrough","dim"],a))}`:s==="active-selected"?`${c("green",Sr)} ${o}${n.hint?` ${c("dim",`(${n.hint})`)}`:""}`:s==="submitted"?`${bt(o,(a)=>c("dim",a))}`:`${c("dim",Ir)} ${bt(o,(a)=>c("dim",a))}`},r=t.required??!0,i=t.showInstructions??!0;return new Pe({options:t.options,signal:t.signal,input:t.input,output:t.output,initialValues:t.initialValues,required:r,cursorAt:t.cursorAt,validate(n){if(r&&(n===void 0||n.length===0))return`Please select at least one option.
|
|
33
|
+
${c("reset",c("dim",`Press ${c(["gray","bgWhite","inverse"]," space ")} to select, ${c("gray",c("bgWhite",c("inverse"," enter ")))} to submit`))}`},render(){let n=t.withGuide??N.withGuide,s=it(t.output,t.message,n?`${Tr(this.state)} `:"",`${Vt(this.state)} `),o=`${n?`${c("gray",w)}
|
|
34
|
+
`:""}${s}
|
|
35
|
+
`,a=this.value??[],u=(l,h)=>{if(l.disabled)return e(l,"disabled");let f=a.includes(l.value);return h&&f?e(l,"active-selected"):f?e(l,"selected"):e(l,h?"active":"inactive")};switch(this.state){case"submit":{let l=this.options.filter(({value:f})=>a.includes(f)).map((f)=>e(f,"submitted")).join(c("dim",", "))||c("dim","none"),h=it(t.output,l,n?`${c("gray",w)} `:"");return`${o}${h}`}case"cancel":{let l=this.options.filter(({value:f})=>a.includes(f)).map((f)=>e(f,"cancelled")).join(c("dim",", "));if(l.trim()==="")return`${o}${c("gray",w)}`;let h=it(t.output,l,n?`${c("gray",w)} `:"");return`${o}${h}${n?`
|
|
36
|
+
${c("gray",w)}`:""}`}case"error":{let l=n?`${c("yellow",w)} `:"",h=this.error.split(`
|
|
37
|
+
`).map((g,d)=>d===0?`${n?`${c("yellow",nt)} `:""}${c("yellow",g)}`:` ${g}`).join(`
|
|
38
|
+
`),f=o.split(`
|
|
39
|
+
`).length,p=h.split(`
|
|
40
|
+
`).length+1;return`${o}${l}${Te({output:t.output,options:this.options,cursor:this.cursor,maxItems:t.maxItems,columnPadding:l.length,rowPadding:f+p,style:u}).join(`
|
|
41
|
+
${l}`)}
|
|
42
|
+
${h}
|
|
43
|
+
`}default:{let l=n?`${c("cyan",w)} `:"",h=o.split(`
|
|
44
|
+
`).length,f=i?Dr(wn,n):n?[c("cyan",nt)]:[],p=f.join(`
|
|
45
|
+
`),g=f.length+1;return`${o}${l}${Te({output:t.output,options:this.options,cursor:this.cursor,maxItems:t.maxItems,columnPadding:l.length,rowPadding:h+g,style:u}).join(`
|
|
46
|
+
${l}`)}
|
|
47
|
+
${p}
|
|
48
|
+
`}}}}).prompt()};var $={message:(t=[],{symbol:e=c("gray",w),secondarySymbol:r=c("gray",w),output:i=process.stdout,spacing:n=1,withGuide:s}={})=>{let o=[],a=s??N.withGuide,u=a?r:"",l=a?`${e} `:"",h=a?`${r} `:"";for(let p=0;p<n;p++)o.push(u);let f=Array.isArray(t)?t:t.split(`
|
|
49
|
+
`);if(f.length>0){let[p,...g]=f;p.length>0?o.push(`${l}${p}`):o.push(a?e:"");for(let d of g)d.length>0?o.push(`${h}${d}`):o.push(a?r:"")}i.write(`${o.join(`
|
|
50
50
|
`)}
|
|
51
|
-
`)},info:(
|
|
52
|
-
`)},
|
|
53
|
-
${
|
|
51
|
+
`)},info:(t,e)=>{$.message(t,{...e,symbol:c("blue",yn)})},success:(t,e)=>{$.message(t,{...e,symbol:c("green",$n)})},step:(t,e)=>{$.message(t,{...e,symbol:c("green",Ut)})},warn:(t,e)=>{$.message(t,{...e,symbol:c("yellow",vn)})},warning:(t,e)=>{$.warn(t,e)},error:(t,e)=>{$.message(t,{...e,symbol:c("red",bn)})}};var Ht=(t="",e)=>{let r=e?.output??process.stdout,i=e?.withGuide??N.withGuide?`${c("gray",pn)} `:"";r.write(`${i}${t}
|
|
52
|
+
`)},Bt=(t="",e)=>{let r=e?.output??process.stdout,i=e?.withGuide??N.withGuide?`${c("gray",w)}
|
|
53
|
+
${c("gray",nt)} `:"";r.write(`${i}${t}
|
|
54
54
|
|
|
55
|
-
`)};var
|
|
56
|
-
`),
|
|
57
|
-
`).map(
|
|
58
|
-
`),
|
|
59
|
-
`:"",
|
|
55
|
+
`)};var Cn=(t)=>t,xn=(t,e,r)=>{let i={hard:!0,trim:!1},n=Y(t,e,i).split(`
|
|
56
|
+
`),s=n.reduce((u,l)=>Math.max(H(l),u),0),o=n.map(r).reduce((u,l)=>Math.max(H(l),u),0),a=e-(o-s);return Y(t,a,i)},dt=(t="",e="",r)=>{let i=r?.output??W.stdout,n=r?.withGuide??N.withGuide,s=r?.format??Cn,o=["",...xn(t,vt(i)-6,s).split(`
|
|
57
|
+
`).map(s),""],a=H(e),u=Math.max(o.reduce((p,g)=>{let d=H(g);return d>p?d:p},0),a)+2,l=o.map((p)=>`${c("gray",w)} ${p}${" ".repeat(u-H(p))}${c("gray",w)}`).join(`
|
|
58
|
+
`),h=n?`${c("gray",w)}
|
|
59
|
+
`:"",f=n?hn:gn;i.write(`${h}${c("green",Ut)} ${c("reset",e)} ${c("gray",Pr.repeat(Math.max(u-a-1,1))+dn)}
|
|
60
|
+
${l}
|
|
61
|
+
${c("gray",f+Pr.repeat(u+2)+fn)}
|
|
62
|
+
`)};var Rn=(t)=>c("magenta",t),B=({indicator:t="dots",onCancel:e,output:r=process.stdout,cancelMessage:i,errorMessage:n,frames:s=Ee?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],delay:o=Ee?80:120,signal:a,...u}={})=>{let l=ln(),h,f,p=!1,g=!1,d="",y,R=performance.now(),E=vt(r),C=u?.styleFrame??Rn,F=(D)=>{let j=D>1?n??N.messages.error:i??N.messages.cancel;g=D===1,p&&(yt(j,D),g&&typeof e=="function"&&e())},A=()=>F(2),x=()=>F(1),L=()=>{process.on("uncaughtExceptionMonitor",A),process.on("unhandledRejection",A),process.on("SIGINT",x),process.on("SIGTERM",x),process.on("exit",F),a&&a.addEventListener("abort",x)},T=()=>{process.removeListener("uncaughtExceptionMonitor",A),process.removeListener("unhandledRejection",A),process.removeListener("SIGINT",x),process.removeListener("SIGTERM",x),process.removeListener("exit",F),a&&a.removeEventListener("abort",x)},P=()=>{if(y===void 0)return;l&&r.write(`
|
|
63
|
+
`);let D=Y(y,E,{hard:!0,trim:!1}).split(`
|
|
64
|
+
`);D.length>1&&r.write(wt.cursor.up(D.length-1)),r.write(wt.cursor.to(0)),r.write(wt.erase.down())},k=(D)=>D.replace(/\.+$/,""),z=(D)=>{let j=(performance.now()-D)/1000,J=Math.floor(j/60),X=Math.floor(j%60);return J>0?`[${J}m ${X}s]`:`[${X}s]`},G=u.withGuide??N.withGuide,At=(D="")=>{p=!0,h=vr({output:r}),d=k(D),R=performance.now(),G&&r.write(`${c("gray",w)}
|
|
65
|
+
`);let j=0,J=0;L(),f=setInterval(()=>{if(l&&d===y)return;P(),y=d;let X=C(s[j]),Tt;if(l)Tt=`${X} ${d}...`;else if(t==="timer")Tt=`${X} ${d} ${z(R)}`;else{let xi=".".repeat(Math.floor(J)).slice(0,3);Tt=`${X} ${d}${xi}`}let Ci=Y(Tt,E,{hard:!0,trim:!1});r.write(Ci),j=j+1<s.length?j+1:0,J=J<4?J+0.125:0},o)},yt=(D="",j=0,J=!1)=>{if(!p)return;p=!1,clearInterval(f),P();let X=j===0?c("green",Ut):j===1?c("red",Er):c("red",Ar);d=D??d,J||(t==="timer"?r.write(`${X} ${d} ${z(R)}
|
|
66
|
+
`):r.write(`${X} ${d}
|
|
67
|
+
`)),T(),h()};return{start:At,stop:(D="")=>yt(D,0),message:(D="")=>{d=k(D??d)},cancel:(D="")=>yt(D,1),error:(D="")=>yt(D,2),clear:()=>yt("",0,!0),get isCancelled(){return g}}},go={light:S("\u2500","-"),heavy:S("\u2501","="),block:S("\u2588","#")};var Sn=[`${c("dim","\u2191/\u2193")} to navigate`,`${c("dim","Enter:")} confirm`],Mt=(t,e)=>t.includes(`
|
|
68
|
+
`)?t.split(`
|
|
69
|
+
`).map((r)=>e(r)).join(`
|
|
70
|
+
`):e(t),Fr=(t)=>{let e=(i,n)=>{if(i===void 0)return"";let s=i.label??String(i.value);switch(n){case"disabled":return`${c("gray",Ot)} ${Mt(s,(o)=>c("gray",o))}${i.hint?` ${c("dim",`(${i.hint??"disabled"})`)}`:""}`;case"selected":return`${Mt(s,(o)=>c("dim",o))}`;case"active":return`${c("green",Ae)} ${s}${i.hint?` ${c("dim",`(${i.hint})`)}`:""}`;case"cancelled":return`${Mt(s,(o)=>c(["strikethrough","dim"],o))}`;default:return`${c("dim",Ot)} ${Mt(s,(o)=>c("dim",o))}`}},r=t.showInstructions??!0;return new Rr({options:t.options,signal:t.signal,input:t.input,output:t.output,initialValue:t.initialValue,render(){let i=t.withGuide??N.withGuide,n=`${Vt(this.state)} `,s=`${Tr(this.state)} `,o=it(t.output,t.message,s,n),a=`${i?`${c("gray",w)}
|
|
71
|
+
`:""}${o}
|
|
72
|
+
`;switch(this.state){case"submit":{let u=i?`${c("gray",w)} `:"",l=it(t.output,e(this.options[this.cursor],"selected"),u);return`${a}${l}`}case"cancel":{let u=i?`${c("gray",w)} `:"",l=it(t.output,e(this.options[this.cursor],"cancelled"),u);return`${a}${l}${i?`
|
|
73
|
+
${c("gray",w)}`:""}`}default:{let u=i?`${c("cyan",w)} `:"",l=a.split(`
|
|
74
|
+
`).length,h=r?Dr(Sn,i):i?[c("cyan",nt)]:[],f=h.join(`
|
|
75
|
+
`),p=h.length+1;return`${a}${u}${Te({output:t.output,cursor:this.cursor,options:this.options,maxItems:t.maxItems,columnPadding:u.length,rowPadding:l+p,style:(g,d)=>e(g,g.disabled?"disabled":d?"active":"inactive")}).join(`
|
|
76
|
+
${u}`)}
|
|
60
77
|
${f}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`).map((
|
|
70
|
-
`)
|
|
71
|
-
`:""}${a}
|
|
72
|
-
|
|
73
|
-
${m("
|
|
74
|
-
`).
|
|
75
|
-
`)
|
|
76
|
-
${c}`)}
|
|
77
|
-
${g}
|
|
78
|
-
`}}}})
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
${s}${e}
|
|
82
|
-
${
|
|
83
|
-
`}case"submit":{let a=t?` ${m("dim",t)}`:"",s=n?m("gray",P):"";return`${o}${s}${a}`}case"cancel":{let a=t?` ${m(["strikethrough","dim"],t)}`:"",s=n?m("gray",P):"";return`${o}${s}${a}${t.trim()?`
|
|
84
|
-
${s}`:""}`}default:{let a=n?`${m("cyan",P)} `:"",s=n?m("cyan",er):"";return`${o}${a}${e}
|
|
85
|
-
${s}
|
|
86
|
-
`}}}}).prompt();var re=!process.env.NO_COLOR&&(process.env.FORCE_COLOR||(process.stdout?.isTTY??!1)),Lo=["black","blue","cyan","gray","green","magenta","red","white","yellow"],ne=["bold","dim","italic","underline","reset"],Io={bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",reset:"\x1B[0m",underline:"\x1B[4m"},oe={black:"\x1B[30m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",green:"\x1B[32m",magenta:"\x1B[35m",red:"\x1B[31m",white:"\x1B[37m",yellow:"\x1B[33m"},ie={black:"\x1B[40m",blue:"\x1B[44m",cyan:"\x1B[46m",gray:"\x1B[100m",green:"\x1B[42m",magenta:"\x1B[45m",red:"\x1B[41m",white:"\x1B[47m",yellow:"\x1B[43m"},ko={"\x1B[30m":"\x1B[90m","\x1B[31m":"\x1B[91m","\x1B[32m":"\x1B[92m","\x1B[33m":"\x1B[93m","\x1B[34m":"\x1B[94m","\x1B[35m":"\x1B[95m","\x1B[36m":"\x1B[96m","\x1B[37m":"\x1B[97m"};function zr(r){return(n)=>re?`${r}${n}${Io.reset}`:n}function ee(r){for(let n=0;n<r.length;n++){let o=r.charCodeAt(n);if(o<32&&o!==27)return!1}return!0}function yo({bright:r=!1,color:n}){let o=Bun.color(n,"ansi"),i=typeof o==="string"&&o.length>0&&ee(o)?o:oe[n];if(!i)return"";return r&&i in ko?ko[i]:i}var te=Lo.reduce((r,n)=>{let o=yo({color:n});if(o)r[n]=zr(o);let i=yo({bright:!0,color:n});if(i)r[`${n}Bright`]=zr(i);return r},{}),ae=ne.reduce((r,n)=>{return r[n]=zr(Io[n]),r},{}),se=Lo.reduce((r,n)=>{let o=ie[n];if(o){let i=`bg${n.charAt(0).toUpperCase()}${n.slice(1)}`;r[i]=zr(o)}return r},{}),p={...te,...ae,...se};function Wr(r){if(lr(r))throw new X;return r}function fe(r){return r.map((n)=>n.key?`${p.bold(n.key)} ${p.dim(n.text)}`:p.dim(n.text)).join(p.dim(" \xB7 "))}function Jr(r){w.info(fe(r))}var Ar={confirm:[{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],multiselect:[{key:"\u2191\u2193",text:"navigate"},{key:"Space",text:"toggle"},{key:"a",text:"all"},{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],select:[{key:"\u2191\u2193",text:"navigate"},{key:"Enter",text:"select"},{key:"Esc",text:"cancel"}],text:[{key:"Enter",text:"submit"},{key:"Esc",text:"cancel"}]};async function br(r){return Jr(Ar.confirm),Wr(await $o(r))}async function rr(r){return Jr(Ar.text),Wr(await Fo(r))}async function tr(r){return Jr(Ar.select),Wr(await Co({showInstructions:!1,...r}))}async function ar(r){return Jr(Ar.multiselect),Wr(await Po({showInstructions:!1,...r}))}var $={arg:p.magenta,cmd:p.cyan,default:p.blue,desc:p.white,flag:p.green,header:(r)=>p.bold(p.yellow(r)),hint:p.dim,name:(r)=>p.bold(p.cyan(r)),placeholder:p.magenta};class $n{metadata;commands;globalArgs;constructor(r,n,o){this.metadata=r;this.commands=n;this.globalArgs=o}version(){return`${$.name(this.metadata.name)} ${$.hint(this.metadata.version??"0.0.0")}`}global(){let r=[],{name:n,bin:o,version:i,description:e}=this.metadata;if(r.push(""),r.push(`${$.name(n)}${i?` ${$.hint(`v${i}`)}`:""}`),e)r.push($.desc(e));r.push(""),r.push($.header("Usage:")),r.push(` ${$.cmd(o)} ${$.placeholder("[command]")} ${$.hint("[options]")}`),r.push(""),r.push($.header("Commands:"));let t=Array.from(this.commands.values()).map((a)=>[` ${$.cmd(a.name)}`,$.desc(a.description)]);return r.push(...this.formatColumns(t)),r.push(""),r.push($.header("Options:")),r.push(...this.formatArgDefs(this.globalArgs)),r.push(""),r.push($.hint(`Run "${o} <command> --help" for command-specific options.`)),r.push(""),r.join(`
|
|
87
|
-
`)}command(r,n){let o=[],i=n??this.metadata.bin,e=`${$.cmd(i)} ${$.cmd(r.name)}`;o.push(""),o.push(`${$.name(r.name)} ${$.hint("-")} ${$.desc(r.description)}`),o.push(""),o.push($.header("Usage:"));let t=this.formatPositionalUsage(r.positionals);if(r.hasSubcommands())o.push(` ${e} ${$.placeholder("<subcommand>")} ${$.hint("[options]")}`);else{let c=[e];if(t)c.push(t);c.push($.hint("[options]")),o.push(` ${c.join(" ")}`)}if(r.prompts)o.push(` ${e} ${$.hint("- runs interactively")}`);if(o.push(""),r.hasSubcommands()){o.push($.header("Subcommands:"));let c=r.getSubcommands().map((f)=>[` ${$.cmd(f.name)}`,$.desc(f.description)]);o.push(...this.formatColumns(c)),o.push("")}if(Object.entries(r.positionals).length>0)o.push($.header("Arguments:")),o.push(...this.formatPositionalDefs(r.positionals)),o.push("");if(Object.entries(r.args).length>0)o.push($.header("Options:")),o.push(...this.formatArgDefs(r.args)),o.push("");return o.join(`
|
|
88
|
-
`)}formatPositionalUsage(r){return Object.entries(r).map(([n,o])=>{let i=o.variadic?`${n}...`:n;return o.required?$.arg(`<${i}>`):$.arg(`[${i}]`)}).join(" ")}formatPositionalDefs(r){let n=Object.entries(r).map(([o,i])=>{let e=i.variadic?`${o}...`:o,t=$.desc(i.description??""),a=i.required?"":$.hint(" (optional)");return[` ${$.arg(e)}`,`${t}${a}`]});return this.formatColumns(n)}formatArgDefs(r){let n=[];for(let[o,i]of Object.entries(r)){let t=`${i.alias?`${$.flag(`-${i.alias}`)}, `:" "}${$.flag(`--${o}`)}`,a=$.desc(i.description??""),s=i.default!==void 0?$.hint(` (default: ${$.default(this.formatDefault(i))})`):"";n.push([` ${t}`,`${a}${s}`])}return this.formatColumns(n)}formatDefault(r){if(r.type==="string")return`"${r.default}"`;return String(r.default)}formatColumns(r){if(r.length===0)return[];let n=Math.max(...r.map(([i])=>this.stripAnsi(i).length)),o=2;return r.map(([i,e])=>{let t=n-this.stripAnsi(i).length+o;return`${i}${" ".repeat(t)}${e}`})}stripAnsi(r){return r.replace(/\x1b\[[0-9;]*m/g,"")}}var nr=new Uint32Array(65536),me=(r,n)=>{let o=r.length,i=n.length,e=1<<o-1,t=-1,a=0,s=o,c=o;while(c--)nr[r.charCodeAt(c)]|=1<<c;for(c=0;c<i;c++){let f=nr[n.charCodeAt(c)],d=f|a;if(f|=(f&t)+t^t,a|=~(f|t),t&=f,a&e)s++;if(t&e)s--;a=a<<1|1,t=t<<1|~(d|a),a&=d}c=o;while(c--)nr[r.charCodeAt(c)]=0;return s},ue=(r,n)=>{let o=n.length,i=r.length,e=[],t=[],a=Math.ceil(o/32),s=Math.ceil(i/32);for(let l=0;l<a;l++)t[l]=-1,e[l]=0;let c=0;for(;c<s-1;c++){let l=0,b=-1,k=c*32,R=Math.min(32,i)+k;for(let C=k;C<R;C++)nr[r.charCodeAt(C)]|=1<<C;for(let C=0;C<o;C++){let N=nr[n.charCodeAt(C)],j=t[C/32|0]>>>C&1,F=e[C/32|0]>>>C&1,E=N|l,M=((N|F)&b)+b^b|N|F,L=l|~(M|b),H=b&M;if(L>>>31^j)t[C/32|0]^=1<<C;if(H>>>31^F)e[C/32|0]^=1<<C;L=L<<1|j,H=H<<1|F,b=H|~(E|L),l=L&E}for(let C=k;C<R;C++)nr[r.charCodeAt(C)]=0}let f=0,d=-1,g=c*32,u=Math.min(32,i-g)+g;for(let l=g;l<u;l++)nr[r.charCodeAt(l)]|=1<<l;let h=i;for(let l=0;l<o;l++){let b=nr[n.charCodeAt(l)],k=t[l/32|0]>>>l&1,R=e[l/32|0]>>>l&1,C=b|f,N=((b|R)&d)+d^d|b|R,j=f|~(N|d),F=d&N;if(h+=j>>>i-1&1,h-=F>>>i-1&1,j>>>31^k)t[l/32|0]^=1<<l;if(F>>>31^R)e[l/32|0]^=1<<l;j=j<<1|k,F=F<<1|R,d=F|~(C|j),f=j&C}for(let l=g;l<u;l++)nr[r.charCodeAt(l)]=0;return h},pe=(r,n)=>{if(r.length<n.length){let o=n;n=r,r=o}if(n.length===0)return r.length;if(r.length<=32)return me(r,n);return ue(r,n)},Do=(r,n)=>{let o=1/0,i=0;for(let e=0;e<n.length;e++){let t=pe(r,n[e]);if(t<o)o=t,i=e}return n[i]};function Kr(r,n,o,i){let e=Do(n,o);if(console.error(p.red(`Unknown ${r}: ${n}`)),e)console.error(p.yellow(`Did you mean "${e}"?`));console.error(`
|
|
89
|
-
Run "${i} --help" for usage.`),process.exit(1)}function vr(r,n){let o=(e)=>e&&typeof e==="object";if(!o(r)||!o(n))return n;let i={...r};for(let e of Object.keys(n)){let t=i[e],a=n[e];if(Array.isArray(t)&&Array.isArray(a))i[e]=[...a];else if(o(t)&&o(a))i[e]=vr(t,a);else i[e]=a}return i}function Pn(r){return r==null?[]:Array.isArray(r)?r:[r]}function le(r,n,o,i){var e,t=r[n],a=~i.string.indexOf(n)?o==null||o===!0?"":String(o):typeof o==="boolean"?o:~i.boolean.indexOf(n)?o==="false"?!1:o==="true"||(r._.push((e=+o,e*0===0)?e:o),!!o):(e=+o,e*0===0)?e:o;r[n]=t==null?a:Array.isArray(t)?t.concat(a):[t,a]}function Yr(r,n){r=r||[],n=n||{};var o,i,e,t,a,s={_:[]},c=0,f=0,d=0,g=r.length;let u=n.alias!==void 0,h=n.unknown!==void 0,l=n.default!==void 0;if(n.alias=n.alias||{},n.string=Pn(n.string),n.boolean=Pn(n.boolean),u)for(o in n.alias){i=n.alias[o]=Pn(n.alias[o]);for(c=0;c<i.length;c++)(n.alias[i[c]]=i.concat(o)).splice(c,1)}for(c=n.boolean.length;c-- >0;){i=n.alias[n.boolean[c]]||[];for(f=i.length;f-- >0;)n.boolean.push(i[f])}for(c=n.string.length;c-- >0;){i=n.alias[n.string[c]]||[];for(f=i.length;f-- >0;)n.string.push(i[f])}if(l){for(o in n.default)if(t=typeof n.default[o],i=n.alias[o]=n.alias[o]||[],n[t]!==void 0){n[t].push(o);for(c=0;c<i.length;c++)n[t].push(i[c])}}let b=h?Object.keys(n.alias):[];for(c=0;c<g;c++){if(e=r[c],e==="--"){s._=s._.concat(r.slice(++c));break}for(f=0;f<e.length;f++)if(e.charCodeAt(f)!==45)break;if(f===0)s._.push(e);else if(e.substring(f,f+3)==="no-"){if(t=e.substring(f+3),h&&!~b.indexOf(t))return n.unknown(e);s[t]=!1}else{for(d=f+1;d<e.length;d++)if(e.charCodeAt(d)===61)break;t=e.substring(f,d),a=e.substring(++d)||(c+1===g||(""+r[c+1]).charCodeAt(0)===45||r[++c]),i=f===2?[t]:t;for(d=0;d<i.length;d++){if(t=i[d],h&&!~b.indexOf(t))return n.unknown("-".repeat(f)+t);le(s,t,d+1<i.length||a,n)}}}if(l){for(o in n.default)if(s[o]===void 0)s[o]=n.default[o]}if(u)for(o in s){i=n.alias[o]||[];while(i.length>0)s[i.shift()]=s[o]}return s}function de(r){return r.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function Ro(r){let n={alias:{},boolean:[],default:{},string:[]};for(let[o,i]of Object.entries(r)){if(i.type==="boolean")n.boolean.push(o);else n.string.push(o);if(i.alias)n.alias[i.alias]=o;let e=de(o);if(e!==o)n.alias[e]=o;if(i.default!==void 0)n.default[o]=i.default}return n}function jo(r,n){let o={...r};for(let[i,e]of Object.entries(n)){if(e.type!=="number")continue;let t=r[i];if(t===void 0||typeof t==="boolean")continue;let a=Number(t);if(Number.isNaN(a))throw Error(`Invalid number for --${i}: "${t}"`);o[i]=a}return o}function Mo(r,n){let o=Ro(n),i=Yr(r,o),e=i._[0],t=e?r.indexOf(e):-1,{_:a,...s}=i,c=jo(s,n);return{command:e,flags:c,restArgs:t>=0?r.slice(t+1):[]}}function Cn(r,n={}){let o=Ro(n),i=Yr(r,o),{_:e,...t}=i;return{args:jo(t,n),rawPositionals:e}}function Fn(r,n){let o={},i=Object.entries(n);for(let[e,[t,a]]of i.entries())o[t]=a.variadic?r.slice(e):r[e];return o}function Uo(r,n){for(let[o,i]of Object.entries(n)){if(!i.required)continue;let e=r[o];if(Array.isArray(e)?e.length===0:!e)return`Missing required argument: <${o}${i.variadic?"...":""}>`}return null}var kn="__exit__";class cr{command;env;prefix;options;constructor(r,n,o,i={}){this.command=r;this.env=n;this.prefix=o;this.options=i}get commandPath(){return this.prefix?`${this.prefix} ${this.command.name}`:this.command.name}async route(r,n){if(n)await this.routeInteractive();else await this.routeDirect(r)}async routeDirect(r){let[n,...o]=r;if(n&&this.command.hasSubcommands()){let i=this.command.getSubcommand(n);if(i){await this.handleSubcommandRoute(i,o);return}if(!n.startsWith("-")){this.handleUnknownSubcommand(n);return}}await this.executeCommand(r)}handleUnknownSubcommand(r){let n=this.command.getSubcommands().map((o)=>o.name);Kr("subcommand",r,n,this.commandPath)}async handleSubcommandRoute(r,n){await new cr(r,this.env,this.commandPath).route(n,!1)}async executeCommand(r){if(this.isHelpRequest(r)){this.printHelp(this.command);return}if(this.command.hasSubcommands()&&!this.command.execute){this.printHelp(this.command);return}if(!this.command.execute)return;let{args:o,rawPositionals:i}=Cn(r,this.command.args),e=Fn(i,this.command.positionals),t=Uo(e,this.command.positionals);if(t)w.error(t),console.error(`
|
|
90
|
-
Run "${this.commandPath} --help" for usage.`),process.exit(1);let a=this.command.prompts&&i.length===0,s=this.buildContext(e,o,a);await this.command.execute(s)}async routeInteractive(){if(!this.command.hasSubcommands()){await this.executeInteractive();return}await this.runSubcommandMenu()}async executeInteractive(){let{args:r}=Cn([],this.command.args),n=Fn([],this.command.positionals),o=this.buildContext(n,r,!0);await this.command.execute?.(o)}async runSubcommandMenu(){while(!0){let r=await this.promptSubcommandSelectionOrBack();if(r===null)return;if(r===kn){this.options.onExit?.();return}let n=this.command.getSubcommand(r);if(n)await this.executeSubcommand(n)}}async promptSubcommandSelectionOrBack(){try{return await this.promptSubcommandSelection()}catch(r){if(r instanceof X){if(this.options.isRoot)this.options.onExit?.();return null}throw r}}async executeSubcommand(r){try{await new cr(r,this.env,this.commandPath).route([],!0)}catch(n){if(n instanceof X)return;if(n instanceof v){if(w.warn(p.yellow(n.message)),n.hint)w.info(p.dim(n.hint));return}throw n}}promptSubcommandSelection(){let{isRoot:r}=this.options,n=r?{hint:this.env.cli.exitHint,label:this.env.cli.exitLabel??"Exit",value:kn}:{hint:"Return to previous menu",label:"Back",value:kn};return tr({message:r?this.env.cli.promptMessage??"Select:":`${this.command.name}:`,options:[...this.command.getSubcommands().map((o)=>({hint:o.description,label:o.name,value:o.name})),n]})}buildContext(r,n,o){return{...this.env,args:n,interactive:o,positionals:r}}isHelpRequest(r){return r.includes("--help")||r.includes("-h")}printHelp(r){let n=r===this.command?this.prefix:this.commandPath;console.log(this.env.formatHelp(r,n))}}var ge={clearOnStart:!0,exitHint:"Close the CLI",exitLabel:"Exit",goodbyeMessage:"Goodbye!",name:"CLI",promptMessage:"What would you like to do?"};class yn{commands=new Map;metadata;configManager;help;bin;globalArgs={help:{alias:"h",description:"Show help",type:"boolean"},interactive:{alias:"i",description:"Enable interactive mode",type:"boolean"},version:{alias:"v",description:"Show version",type:"boolean"}};constructor(r,n){this.configManager=r,this.metadata={...ge,...n},this.bin=this.metadata.bin??this.metadata.name,this.init(),this.help=new $n({bin:this.bin,description:this.metadata.description,name:this.metadata.name,version:this.metadata.version},this.commands,this.globalArgs)}registerCommands(r){for(let n of r)n.init?.(),this.commands.set(n.name,n)}async run(r=process.argv.slice(2)){let{command:n,flags:o,restArgs:i}=Mo(r,this.globalArgs);if(o.version&&!n)return console.log(this.help.version());if(o.interactive&&!n)return this.runInteractive();if(!n)return console.log(this.help.global());if(n==="help")return this.printHelpFor(i[0]);await this.runDirect(n,i,!!o.help)}printHelpFor(r){if(!r)return console.log(this.help.global());let n=this.commands.get(r);if(!n)return this.handleUnknownCommand(r);console.log(this.help.command(n))}async runInteractive(){this.showIntro();let r=this.createVirtualRootCommand(),n={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)},o=new cr(r,n,this.bin,{isRoot:!0,onExit:()=>this.exit()});try{await o.route([],!0)}catch(i){this.handleError(i)}}createVirtualRootCommand(){return{description:this.metadata.description,getSubcommand:(r)=>this.commands.get(r),getSubcommands:()=>Array.from(this.commands.values()),hasSubcommands:()=>!0,name:this.metadata.name}}exit(){Gr(this.metadata.goodbyeMessage),process.exit(0)}async runDirect(r,n,o){let i=this.commands.get(r);if(!i)return this.handleUnknownCommand(r);let e=n.length>0&&!n[0]?.startsWith("-");if(o&&!e)return console.log(this.help.command(i));try{let t={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)};await new cr(i,t,this.bin).route(n,!1)}catch(t){this.handleError(t)}}showIntro(){if(this.metadata.clearOnStart)console.clear();let r=this.metadata.version?` v${this.metadata.version}`:"";qr(`${p.bgCyan(p.black(` ${this.metadata.name}${r} `))}`)}handleUnknownCommand(r){let n=Array.from(this.commands.keys());Kr("command",r,n,this.bin)}handleError(r){if(this.metadata.onError?.(r))return;if(r instanceof X)process.exit(0);if(r instanceof v){if(w.warn(p.yellow(r.message)),r.hint)w.info(p.dim(r.hint));process.exit(0)}if(r instanceof Error)w.error(p.red(r.message)),process.exit(1);console.error(p.red("Error:"),r),process.exit(1)}}class wr{args={};positionals={};prompts=!1;subcommands=new Map;registerSubcommands(r){for(let n of r)n.init?.(),this.subcommands.set(n.name,n)}hasSubcommands(){return this.subcommands.size>0}getSubcommand(r){return this.subcommands.get(r)}getSubcommands(){return Array.from(this.subcommands.values())}}function fr(r){return r}function G(r){return r}import mr from"fs";import Ho from"path";class Ln{config;configPath;defaultConfig;constructor(r,n){this.configPath=Ho.resolve(r),this.defaultConfig=n,this.config=this.loadConfig()}get(r){return this.config[r]}set(r,n){this.config[r]=n,this.save()}delete(r){delete this.config[r],this.save()}exists(){return mr.existsSync(this.configPath)}getAll(){return vr({},this.config)}save(r){if(r)this.config={...r};this.ensureDirectoryExists();try{mr.writeFileSync(this.configPath,JSON.stringify(this.config,null,2))}catch(n){console.error(`Failed to save config to ${this.configPath}:`,n)}}ensureDirectoryExists(){let r=Ho.dirname(this.configPath);if(!mr.existsSync(r))try{mr.mkdirSync(r,{recursive:!0})}catch(n){console.error(`Failed to create config directory at ${r}:`,n)}}loadConfig(){if(!mr.existsSync(this.configPath))return{...this.defaultConfig};try{let r=mr.readFileSync(this.configPath,"utf-8"),n=JSON.parse(r);return vr({...this.defaultConfig},n)}catch{return console.warn(`Config file corrupted at ${this.configPath}. Using defaults.`),{...this.defaultConfig}}}}var Eo="0.6.0";import{join as De}from"path";class I extends wr{}import{existsSync as Fr}from"fs";import{cp as Ce,link as Fe,mkdir as Un,readdir as Ko,readFile as Hn,readlink as ke,rm as En,symlink as ye,unlink as Yo,writeFile as Le}from"fs/promises";import{join as D,resolve as xr}from"path";var Zr="hydra";var No=".hydra/config.json",$r=".hydra/shared",Pr=".hydra/runners",Cr="default",qo={profiles:{}};import{existsSync as be}from"fs";import{readdir as ve,stat as we}from"fs/promises";import{join as $e}from"path";var In="_diag",Go={runner:/^Runner_.+\.log$/,worker:/^Worker_.+\.log$/},zo=1024,Wo=["B","KB","MB","GB"],Pe=1;function Jo(r){if(Go.worker.test(r))return"worker";if(Go.runner.test(r))return"runner";return null}function Ao(r){return[...r].sort((n,o)=>o.mtime.getTime()-n.mtime.getTime())}async function Dn(r){if(!be(r))return[];let n=await ve(r,{withFileTypes:!0}),o=[];for(let i of n){if(!i.isFile())continue;let e=Jo(i.name);if(!e)continue;let t=$e(r,i.name),a=await we(t);o.push({mtime:a.mtime,name:i.name,path:t,size:a.size,type:e})}return Ao(o)}function Rn(r,n){let o=r.find((e)=>e.type===n);if(o)return{fallback:!1,file:o};let i=r[0];return i?{fallback:!0,file:i}:null}function jn(r,n){if(n<=0)return"";let o=r.endsWith(`
|
|
91
|
-
`)?r.slice(0,-1):r;if(o==="")return"";return o.split(`
|
|
92
|
-
`).slice(-n).join(`
|
|
93
|
-
`)}function Mn(r){let n=r,o=0;while(n>=zo&&o<Wo.length-1)n/=zo,o++;return`${o===0?String(n):n.toFixed(Pe)} ${Wo[o]??"B"}`}var Zo="actions/runner",Ie={linux:"linux-x64",osx:"osx-arm64",windows:"win-x64"},xo=["bin"],Qo=["externals"];class Qr{profile;sharedPath=null;constructor(r){this.profile=r}async download(){let r=Ie[this.profile.os],n=await this.getLatestVersion(),o=D($r,"github",n);if(Fr(o))return this.sharedPath=o,{path:o,version:n};await Un(o,{recursive:!0});let i=`actions-runner-${r}-${n}.tar.gz`,e=D(o,i),t=`https://github.com/${Zo}/releases/download/v${n}/${i}`;return await Bun.$`curl -sL -o ${e} ${t}`,await Bun.$`tar xzf ${e} -C ${o}`,await Yo(e),this.sharedPath=o,{path:o,version:n}}async create(r){let n=await this.ensureDownloaded(),o=[];for(let i of r){let e=D(this.profile.directory,i);await this.setupRunnerDir(n,e),await this.registerRunner(e,i),o.push({directory:e,id:i,name:i,status:"registered"})}return o}async remove(r){for(let n of r){let o=D(this.profile.directory,n);if(!Fr(D(o,".runner")))continue;let i=await this.fetchRemovalToken(o);await Bun.$`bash ./config.sh remove --token ${i}`.cwd(o).quiet().nothrow()}}async start(r){for(let n of r){let o=D(this.profile.directory,n),i=await this.readPidFile(o);if(i&&this.isProcessRunning(i))continue;let e=Bun.spawn(["bash","./run.sh"],{cwd:xr(o),stderr:"pipe",stdout:"pipe"});e.unref(),await this.writePidFile(o,e.pid)}}async stop(r){for(let n of r){let o=D(this.profile.directory,n);if(!await this.readPidFile(o))continue;let e=xr(o);await Bun.$`pkill -f ${e}`.quiet().nothrow(),await this.removePidFile(o)}}async list(){let r=this.profile.directory;if(!Fr(r))return[];let n=await Ko(r,{withFileTypes:!0}),o=[];for(let i of n){if(!i.isDirectory())continue;let e=D(r,i.name);o.push(await this.getRunnerStatus(e,i.name))}return o}async currentVersion(r){let n=D(this.profile.directory,r);return this.detectVersion(n)}async logFiles(r){return Dn(D(this.profile.directory,r,In))}async update(r){let n=await this.ensureDownloaded();for(let o of r){let i=D(this.profile.directory,o);await this.removeRunnerBinaries(i),await this.setupRunnerDir(n,i)}}async getRunnerStatus(r,n){let o=await this.readRunnerName(r),i=await this.readPidFile(r),e=i!==null&&this.isProcessRunning(i),t="unknown";if(e)t="running";else if(Fr(D(r,".runner")))t="registered";return{directory:r,id:n,name:o,pid:e?i:void 0,status:t}}async ensureDownloaded(){if(this.sharedPath)return this.sharedPath;let{path:r}=await this.download();return r}async setupRunnerDir(r,n){await Un(n,{recursive:!0});for(let o of xo)await this.hardLinkDir(D(r,o),D(n,o));for(let o of Qo){let i=xr(r,o),e=D(n,o);if(!Fr(e))await ye(i,e)}for(let o of["*.sh","*.sh.template"]){let i=await Array.fromAsync(new Bun.Glob(o).scan(r));for(let e of i)await Ce(D(r,e),D(n,e))}}async registerRunner(r,n){let o=await this.fetchRegistrationToken(),i=["--url",this.profile.url,"--token",o,"--name",n,"--unattended"];if(this.profile.labels)i.push("--labels",this.profile.labels);if(this.profile.runnerGroup)i.push("--runnergroup",this.profile.runnerGroup);await Bun.$`bash ./config.sh ${i}`.cwd(r).quiet()}async fetchRegistrationToken(){let{owner:r,repo:n}=this.parseUrl(this.profile.url),i=(await Bun.$`gh api repos/${r}/${n}/actions/runners/registration-token --method POST --jq .token`.quiet()).stdout.toString().trim();if(!i)throw Error(`Failed to fetch registration token for ${r}/${n}`);return i}async fetchRemovalToken(r){let n=await Hn(D(r,".runner"),"utf-8"),i=JSON.parse(this.stripBom(n)).gitHubUrl;if(!i)throw Error("Cannot determine GitHub URL from runner config");let{owner:e,repo:t}=this.parseUrl(i);return(await Bun.$`gh api repos/${e}/${t}/actions/runners/remove-token --method POST --jq .token`.quiet()).stdout.toString().trim()}async getLatestVersion(){return(await Bun.$`gh api repos/${Zo}/releases/latest --jq .tag_name`.quiet()).stdout.toString().trim().replace(/^v/,"")}parseUrl(r){let n=r.match(/github\.com\/([^/]+)\/([^/.]+)/);if(!n?.[1]||!n[2])throw Error(`Invalid GitHub URL: ${r}`);return{owner:n[1],repo:n[2]}}pidFilePath(r){return xr(r,".pid")}async writePidFile(r,n){await Le(this.pidFilePath(r),String(n))}async readPidFile(r){try{let n=await Hn(this.pidFilePath(r),"utf-8");return Number.parseInt(n.trim(),10)}catch{return null}}async removePidFile(r){try{await Yo(this.pidFilePath(r))}catch{}}async readRunnerName(r){try{let n=await Hn(D(r,".runner"),"utf-8");return JSON.parse(this.stripBom(n)).agentName??"unknown"}catch{return"unknown"}}async hardLinkDir(r,n){await Un(n,{recursive:!0});let o=await Ko(r,{withFileTypes:!0});for(let i of o){let e=D(r,i.name),t=D(n,i.name);if(i.isDirectory())await this.hardLinkDir(e,t);else await Fe(e,t)}}async detectVersion(r){try{return(await ke(D(r,"externals"))).match(/github\/([^/]+)/)?.[1]??null}catch{return null}}async removeRunnerBinaries(r){for(let n of xo)await En(D(r,n),{force:!0,recursive:!0});for(let n of Qo)await En(D(r,n),{force:!0});for(let n of["*.sh","*.sh.template"]){let o=await Array.fromAsync(new Bun.Glob(n).scan(r));for(let i of o)await En(D(r,i),{force:!0})}}stripBom(r){return r.replace(/^\uFEFF/,"")}isProcessRunning(r){try{return process.kill(r,0),!0}catch{return!1}}}function z(r){switch(r.provider){case"github":return new Qr(r);default:throw Error(`Runner provider "${r.provider}" is not yet implemented`)}}function ur(r,n){if(r.length===0)return n;for(let o of r)if(!n.includes(o))throw new v(`Runner "${o}" not found`);return r}function J(r,n){let o=r.get("profiles");if(Object.keys(o).length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=n??r.get("defaultProfile")??Cr,e=o[i];if(!e)throw new v(`Profile "${i}" not found`);return{name:i,profile:e}}async function Q(r){let n=r.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");if(o.length===1)return o[0];return tr({message:"Select profile",options:o.map((i)=>({label:i,value:i,hint:n[i]?.url}))})}var Re=G({profile:{description:"Profile name"},count:{description:"Number of runners to create (overrides profile)"}});class Xr extends I{name="create";description="Create and register runners";positionals=Re;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),i=r.interactive?await this.promptCount(o.numberOfMachines):r.positionals.count?Number.parseInt(r.positionals.count,10):o.numberOfMachines;if(!i||i<1)throw new v("Runner count must be at least 1");let e=z(o),t=Y();t.start("Downloading runner binary...");let{version:a}=await e.download();t.stop(`Runner v${a} ready`);let s=r.config.get("runners")??[],c=s.filter((l)=>l.profile===n),f=i-c.length;if(f<=0){w.warn(`Already have ${c.length} runner(s) for profile "${n}". Nothing to create.`);return}let d=new Set(s.map((l)=>l.id)),g=1;for(let l=0;l<f;){let b=`${o.name}-${g++}`;if(d.has(b))continue;l++,t.start(`Registering ${b}...`),await e.create([b]),t.stop(`${p.green("+")} ${b}`),s.push({createdAt:new Date().toISOString(),directory:De(o.directory,b),id:b,name:b,profile:n,provider:o.provider,url:o.url})}r.config.set("runners",s);let h=n===r.config.get("defaultProfile")?"":` ${n}`;w.info(`${p.green("Created")} ${f} runner(s) for "${n}". Run ${p.green(`hydra start${h}`)} to start them.`)}async promptCount(r){let n=await rr({initialValue:String(r),message:"Number of runners to create",validate:(o)=>{let i=Number.parseInt(o??"",10);if(Number.isNaN(i)||i<1)return"Must be a positive number";return}});return Number.parseInt(n,10)}}import{existsSync as Xo}from"fs";import{mkdir as Vo}from"fs/promises";var je=G({url:{description:"GitHub repository or organization URL"}}),Me=fr({force:{alias:"f",default:!1,description:"Overwrite existing config",type:"boolean"},labels:{alias:"l",description:"Comma-separated runner labels",type:"string"},name:{alias:"n",description:"Base name for runners",type:"string"},profile:{alias:"p",description:"Profile name",type:"string"},runners:{alias:"c",description:"Number of runners to create",type:"number"}});class Vr extends I{name="init";description="Initialize Hydra runner manager";positionals=je;args=Me;prompts=!0;async execute(r){let n=r.interactive?await this.promptProfileName(r):r.args.profile??Cr,o=!r.config.exists();if(!o&&r.config.get("profiles")[n]&&!r.args.force){if(!r.interactive)throw new v(`Profile "${n}" already exists. Use --force to overwrite.`);if(!await br({initialValue:!1,message:`Profile "${n}" already exists. Overwrite?`}))return}await this.ensureDirectories();let e=r.interactive?await this.runInitForm():this.buildProfileFromArgs(r),t=o?{}:{...r.config.get("profiles")};if(t[n]=e,r.config.set("profiles",t),!r.config.get("defaultProfile"))r.config.set("defaultProfile",n);sr([`${p.dim("Profile:")} ${n}`,`${p.dim("URL:")} ${e.url}`,`${p.dim("Runners:")} ${e.numberOfMachines}`,`${p.dim("Name:")} ${e.name}`,e.labels?`${p.dim("Labels:")} ${e.labels}`:"","",`Run ${p.green(`${Zr} create${n!==r.config.get("defaultProfile")?` ${n}`:""}`)} to provision runners.`].filter(Boolean).join(`
|
|
94
|
-
`),p.green(o?"Hydra initialized":`Profile "${n}" added`))}async promptProfileName(r){return rr({initialValue:r.args.profile??Cr,message:"Profile name"})}async ensureDirectories(){if(!Xo($r))await Vo($r,{recursive:!0});if(!Xo(Pr))await Vo(Pr,{recursive:!0})}async runInitForm(){let r=await Nr({url:()=>rr({message:"GitHub repository or organization URL",placeholder:"https://github.com/owner/repo",validate:(n)=>{if(!n)return"URL is required";try{new URL(n)}catch{return"Must be a valid URL"}return}}),name:()=>rr({initialValue:"runner",message:"Base name for runners",placeholder:"runner"}),runners:()=>rr({initialValue:"1",message:"Number of runners",placeholder:"1",validate:(n)=>{if(!n)return"Must be a positive number";let o=Number.parseInt(n,10);if(Number.isNaN(o)||o<1)return"Must be a positive number";return}}),labels:()=>rr({message:"Additional labels (comma-separated, optional)",placeholder:"self-hosted,macOS,ARM64"})},{onCancel:()=>{throw new X}});return{directory:Pr,labels:r.labels||void 0,name:r.name,numberOfMachines:Number.parseInt(r.runners,10)||1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:r.url}}buildProfileFromArgs(r){if(!r.positionals.url)throw new v("URL is required","Usage: hydra init <url>");return this.validateUrl(r.positionals.url),this.validateRunnerCount(r.args.runners),{directory:Pr,labels:r.args.labels,name:r.args.name??"runner",numberOfMachines:r.args.runners??1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:r.positionals.url}}validateUrl(r){try{new URL(r)}catch{throw new v(`Invalid URL: ${r}`)}}validateRunnerCount(r){if(r!==void 0&&r<1)throw new v("Runner count must be at least 1")}detectOs(){let r=process.platform;if(r==="darwin")return"osx";if(r==="win32")return"windows";return"linux"}}import{existsSync as Ue}from"fs";import{readFile as He}from"fs/promises";var Ee=100,Ne={runner:"runner daemon log",worker:"job log"},qe=fr({lines:{alias:"n",default:Ee,description:"Number of lines to tail",type:"number"},list:{alias:"l",default:!1,description:"List available log files instead of printing content",type:"boolean"},open:{alias:"o",default:!1,description:"Open the log file in $EDITOR instead of printing",type:"boolean"},runner:{alias:"r",default:!1,description:"Show the runner daemon log instead of the latest job log",type:"boolean"}}),Ge=G({id:{description:"Runner ID"}});class Or extends I{name="logs";description="Inspect logs of the latest jobs";args=qe;positionals=Ge;async execute(r){let n=r.config.get("runners")??[];if(n.length===0)throw new v("No runners found","Run hydra create to provision runners");let o=await this.resolveEntry(r,n),i=r.config.get("profiles")[o.profile];if(!i)throw new v(`Profile "${o.profile}" not found for runner "${o.id}"`,"Run hydra init to set it up");if(!Ue(o.directory))throw new v(`Runner directory not found: ${o.directory}`,"Run hydra create to provision this runner");let t=await z(i).logFiles(o.id);if(t.length===0)this.noLogs(o.id);if(r.args.list){this.printList(o,t);return}let a=this.selectFile(r,o,t);if(r.args.open){await this.openFile(a);return}await this.printTail(o,a,r.args.lines)}async resolveEntry(r,n){let o=r.positionals.id;if(o){let e=n.find((t)=>t.id===o);if(!e)throw new v(`Runner "${o}" not found`,`Known runners: ${n.map((t)=>t.id).join(", ")}`);return e}if(r.interactive)return tr({message:"Select runner",options:n.map((e)=>({hint:e.profile,label:e.name,value:e}))});let i=n[0];if(n.length===1&&i)return i;throw new v("Multiple runners found",`Pass a runner id: hydra logs <id> (${n.map((e)=>e.id).join(", ")})`)}selectFile(r,n,o){if(r.args.runner){let e=o.find((t)=>t.type==="runner");if(!e)throw new v(`No runner daemon logs found for "${n.id}"`,"Start the runner first: hydra start");return e}let i=Rn(o,"worker");if(!i)this.noLogs(n.id);if(i.fallback)w.warn(p.yellow("No job (Worker) logs yet; showing the runner daemon log instead"));return i.file}noLogs(r){throw new v(`No logs found for runner "${r}"`,"Logs appear once the runner has started; run hydra start")}printList(r,n){let o=[`${p.bold(r.name)} ${p.dim(r.directory)}`];for(let i of n){let e=i.type==="worker"?p.green("worker"):p.blue("runner");o.push(` ${e} ${i.name} ${p.dim(`${i.mtime.toISOString()} \xB7 ${Mn(i.size)}`)}`)}w.info(o.join(`
|
|
95
|
-
`))}async printTail(r,n,o){let i=await He(n.path,"utf-8"),e=[`${p.bold(r.name)} ${p.dim(Ne[n.type])}`,p.dim(n.path),p.dim(`Last modified: ${n.mtime.toISOString()}`)];w.info(e.join(`
|
|
96
|
-
`)),console.log(jn(i,o))}async openFile(r){let n=(process.env.EDITOR??"").split(" ").filter(Boolean),o=n[0];if(o){await Bun.spawn([o,...n.slice(1),r.path],{stderr:"inherit",stdin:"inherit",stdout:"inherit"}).exited;return}if(process.platform==="darwin"){await Bun.$`open ${r.path}`.quiet();return}throw new v("No editor configured","Set $EDITOR to open log files")}}var ze=G({name:{description:"Profile name to set as default"}});class Nn extends I{name="default";description="Set the default profile";positionals=ze;async execute(r){let n=r.interactive?await Q(r.config):r.positionals.name;if(!n)throw new v("Profile name is required","Usage: hydra profile default <name>");let{name:o}=J(r.config,n);if(r.config.get("defaultProfile")===o){w.info(`"${o}" is already the default profile.`);return}r.config.set("defaultProfile",o),w.info(`${p.green("Default profile set to")} "${o}".`)}}class qn extends I{name="list";description="List all profiles";async execute(r){let n=r.config.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=r.config.get("runners")??[],e=r.config.get("defaultProfile");for(let t of o){let a=n[t],c=await z(a).list(),f=i.filter((b)=>b.profile===t),d=new Set(c.filter((b)=>b.status==="running").map((b)=>b.id)),g=f.filter((b)=>d.has(b.id)).length,u=t===e,h=[`${p.dim("URL:")} ${a.url}`,`${p.dim("Provider:")} ${a.provider}`,`${p.dim("OS:")} ${a.os}`,`${p.dim("Name:")} ${a.name}`,`${p.dim("Runners:")} ${f.length}/${a.numberOfMachines} created, ${p.green(`${g} running`)}`];if(a.labels)h.push(`${p.dim("Labels:")} ${a.labels}`);let l=u?`${t} ${p.dim("(default)")}`:t;sr(h.join(`
|
|
97
|
-
`),l)}w.info(p.dim(`${o.length} profile(s)`))}}import{rm as We}from"fs/promises";import{join as Je}from"path";var Ae=G({name:{description:"Profile name to remove"}});class Gn extends I{name="remove";description="Remove a profile";positionals=Ae;async execute(r){let n=r.interactive?await Q(r.config):r.positionals.name;if(!n)throw new v("Profile name is required","Usage: hydra profile remove <name>");let{profile:o}=J(r.config,n),i=r.config.get("runners")??[],e=i.filter((c)=>c.profile===n);if(e.length>0){if(!await br({initialValue:!0,message:`This will stop and remove ${e.length} runner(s). Continue?`}))return;await this.removeRunners(o,e.map((d)=>d.id));let f=i.filter((d)=>d.profile!==n);r.config.set("runners",f)}let{[n]:t,...a}=r.config.get("profiles");if(r.config.set("profiles",a),r.config.get("defaultProfile")===n){let c=Object.keys(a);r.config.set("defaultProfile",c[0])}w.info(`${p.green("Removed")} profile "${n}".`)}async removeRunners(r,n){let o=z(r),i=Y();for(let e of n)i.start(`Stopping and removing ${e}...`),await o.stop([e]),await o.remove([e]),await We(Je(r.directory,e),{force:!0,recursive:!0}),i.stop(`${p.red("-")} ${e}`)}}class Sr extends I{name="profile";description="Manage profiles";init(){this.registerSubcommands([new qn,new Gn,new Nn])}}import{rm as Ke}from"fs/promises";import{join as Ye}from"path";var Ze=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class Br extends I{name="remove";description="Deregister and remove runners";positionals=Ze;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),i=r.config.get("runners")??[],e=i.filter((f)=>f.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=r.interactive?await this.promptRunnerSelection(e.map((f)=>f.id)):ur(r.positionals.ids??[],e.map((f)=>f.id)),a=z(o),s=Y();for(let f of t)s.start(`Stopping and removing ${f}...`),await a.stop([f]),await a.remove([f]),await Ke(Ye(o.directory,f),{force:!0,recursive:!0}),s.stop(`${p.red("-")} ${f}`);let c=i.filter((f)=>!t.includes(f.id));r.config.set("runners",c),w.info(`${p.green("Removed")} ${t.length} runner(s).`)}async promptRunnerSelection(r){return ar({message:"Select runners to remove",options:r.map((n)=>({label:n,value:n})),required:!0})}}var xe=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class _r extends I{name="start";description="Start runners";positionals=xe;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),e=(r.config.get("runners")??[]).filter((u)=>u.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=z(o),a=Y();a.start("Fetching runner status...");let s=await t.list();a.stop("Runner status fetched");let c=new Set(s.filter((u)=>u.status==="running").map((u)=>u.id)),f=e.map((u)=>u.id).filter((u)=>!c.has(u)),d=r.interactive?await this.promptRunnerSelection(f):ur(r.positionals.ids??[],e.map((u)=>u.id)),g=0;for(let u of d){if(c.has(u)){a.start(""),a.stop(`${p.dim("\u25CF")} ${u} ${p.dim("already running")}`);continue}a.start(`Starting ${u}...`),await t.start([u]),a.stop(`${p.green("\u25B6")} ${u}`),g++}w.info(`${p.green("Started")} ${g} runner(s).`)}async promptRunnerSelection(r){if(r.length===0)throw new v("All runners are already running");return ar({message:"Select runners to start",options:r.map((n)=>({label:n,value:n})),required:!0})}}var Qe={registered:p.yellow,running:p.green,stopped:p.red,unknown:p.dim};class Tr extends I{name="status";description="Show runner status across all profiles";async execute(r){let n=r.config.get("profiles"),o=Object.keys(n);if(o.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=r.config.get("runners")??[],e=0,t=0,a=[];for(let s of o){let c=n[s],d=await z(c).list();if(a.length>0)a.push("");a.push(`${p.bold(s)} ${p.dim(c.url)}`);let g=new Set(i.filter((h)=>h.profile===s).map((h)=>h.id)),u=d.filter((h)=>g.has(h.id)).sort((h,l)=>h.name.localeCompare(l.name,void 0,{numeric:!0}));this.formatRunners(u,a),e+=u.length,t+=u.filter((h)=>h.status==="running").length}a.push(""),a.push(p.dim(`${e} runner(s) total, ${t} running`)),w.info(a.join(`
|
|
98
|
-
`))}formatRunners(r,n){if(r.length===0){n.push(p.dim(" No runners."));return}for(let o of r){let i=Qe[o.status]??p.dim,e=o.pid?p.dim(` (pid: ${o.pid})`):"";n.push(` ${i("\u25CF")} ${o.name} ${i(o.status)}${e}`)}}}var Xe=G({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class rn extends I{name="stop";description="Stop runners";positionals=Xe;async execute(r){let{name:n,profile:o}=r.interactive?J(r.config,await Q(r.config)):J(r.config,r.positionals.profile),e=(r.config.get("runners")??[]).filter((u)=>u.profile===n);if(e.length===0)throw new v(`No runners found for profile "${n}"`,"Run hydra create to provision runners");let t=z(o),a=Y();a.start("Fetching runner status...");let s=await t.list();a.stop("Runner status fetched");let c=new Set(s.filter((u)=>u.status==="running").map((u)=>u.id)),f=e.map((u)=>u.id).filter((u)=>c.has(u)),d=r.interactive?await this.promptRunnerSelection(f):ur(r.positionals.ids??[],e.map((u)=>u.id)),g=0;for(let u of d){if(!c.has(u)){a.start(""),a.stop(`${p.dim("\u25CF")} ${u} ${p.dim("not running")}`);continue}a.start(`Stopping ${u}...`),await t.stop([u]),a.stop(`${p.red("\u25A0")} ${u}`),g++}w.info(`${p.green("Stopped")} ${g} runner(s).`)}async promptRunnerSelection(r){if(r.length===0)throw new v("No runners are currently running");return ar({message:"Select runners to stop",options:r.map((n)=>({label:n,value:n})),required:!0})}}class nn extends I{name="update";description="Update runners to the latest version";async execute(r){let n=r.config.get("profiles"),o=r.config.get("runners")??[];if(o.length===0)throw new v("No runners found","Run hydra create to provision runners");let i=Y(),e=Map.groupBy(o,(c)=>c.profile),t=null,a="",s=!1;for(let[c,f]of e){let d=n[c],g=f[0];if(!d||!g)continue;let u=z(d);if(!s){if(s=!0,i.start("Checking for updates..."),a=(await u.download()).version,t=await u.currentVersion(g.id),i.stop(`Current: v${t??"unknown"} | Latest: v${a}`),t===a){w.info(`Already on latest version ${p.dim(`(v${a})`)}`);return}}let h=await u.list(),l=new Set(h.filter((b)=>b.status==="running").map((b)=>b.id));for(let b of f){let k=l.has(b.id);if(i.start(`Updating ${b.id}...`),k)await u.stop([b.id]);if(await u.update([b.id]),k)await u.start([b.id]);let R=k?` ${p.dim("(restarted)")}`:"";i.stop(`${p.green("\u2713")} ${b.id}${R}`)}}w.info(`${p.green("Updated")} ${o.length} runner(s) from v${t} to v${a}`)}}class Oo extends yn{constructor(){super(new Ln(No,qo),{bin:Zr,clearOnStart:!0,exitLabel:"Exit",goodbyeMessage:"Heads down.",name:"HYDRA",promptMessage:"What do you need?",version:Eo})}init(){this.registerCommands([new Vr,new Xr,new _r,new rn,new Tr,new Or,new Br,new nn,new Sr])}}var Ve=new Oo;Ve.run();
|
|
78
|
+
`}}}}).prompt()};var yo=`${c("gray",w)} `;var Nr=(t)=>new _e({validate:t.validate,placeholder:t.placeholder,defaultValue:t.defaultValue,initialValue:t.initialValue,output:t.output,signal:t.signal,input:t.input,render(){let e=t?.withGuide??N.withGuide,r=`${`${e?`${c("gray",w)}
|
|
79
|
+
`:""}${Vt(this.state)} `}${t.message}
|
|
80
|
+
`,i=t.placeholder&&t.placeholder.length>0?c("inverse",t.placeholder[0])+c("dim",t.placeholder.slice(1)):c(["inverse","hidden"],"_"),n=this.userInput?this.userInputWithCursor:i,s=this.value??"";switch(this.state){case"error":{let o=this.error?` ${c("yellow",this.error)}`:"",a=e?`${c("yellow",w)} `:"",u=e?c("yellow",nt):"";return`${r.trim()}
|
|
81
|
+
${a}${n}
|
|
82
|
+
${u}${o}
|
|
83
|
+
`}case"submit":{let o=s?` ${c("dim",s)}`:"",a=e?c("gray",w):"";return`${r}${a}${o}`}case"cancel":{let o=s?` ${c(["strikethrough","dim"],s)}`:"",a=e?c("gray",w):"";return`${r}${a}${o}${s.trim()?`
|
|
84
|
+
${a}`:""}`}default:{let o=e?`${c("cyan",w)} `:"",a=e?c("cyan",nt):"";return`${r}${o}${n}
|
|
85
|
+
${a}
|
|
86
|
+
`}}}}).prompt();var Pn=!process.env.NO_COLOR&&(process.env.FORCE_COLOR||(process.stdout?.isTTY??!1)),Ur=["black","blue","cyan","gray","green","magenta","red","white","yellow"],_n=["bold","dim","italic","underline","reset"],Vr={bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",reset:"\x1B[0m",underline:"\x1B[4m"},En={black:"\x1B[30m",blue:"\x1B[34m",cyan:"\x1B[36m",gray:"\x1B[90m",green:"\x1B[32m",magenta:"\x1B[35m",red:"\x1B[31m",white:"\x1B[37m",yellow:"\x1B[33m"},An={black:"\x1B[40m",blue:"\x1B[44m",cyan:"\x1B[46m",gray:"\x1B[100m",green:"\x1B[42m",magenta:"\x1B[45m",red:"\x1B[41m",white:"\x1B[47m",yellow:"\x1B[43m"},Mr={"\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 jt(t){return(e)=>Pn?`${t}${e}${Vr.reset}`:e}function Tn(t){for(let e=0;e<t.length;e++){let r=t.charCodeAt(e);if(r<32&&r!==27)return!1}return!0}function Or({bright:t=!1,color:e}){let r=Bun.color(e,"ansi"),i=typeof r==="string"&&r.length>0&&Tn(r)?r:En[e];if(!i)return"";return t&&i in Mr?Mr[i]:i}var Dn=Ur.reduce((t,e)=>{let r=Or({color:e});if(r)t[e]=jt(r);let i=Or({bright:!0,color:e});if(i)t[`${e}Bright`]=jt(i);return t},{}),kn=_n.reduce((t,e)=>(t[e]=jt(Vr[e]),t),{}),Ln=Ur.reduce((t,e)=>{let r=An[e];if(r){let i=`bg${e.charAt(0).toUpperCase()}${e.slice(1)}`;t[i]=jt(r)}return t},{}),m={...Dn,...kn,...Ln};function Wt(t){if($t(t))throw new q;return t}function Nn(t){return t.map((e)=>e.key?`${m.bold(e.key)} ${m.dim(e.text)}`:m.dim(e.text)).join(m.dim(" \xB7 "))}function Kt(t){$.info(Nn(t))}var qt={confirm:[{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],multiselect:[{key:"\u2191\u2193",text:"navigate"},{key:"Space",text:"toggle"},{key:"a",text:"all"},{key:"Enter",text:"confirm"},{key:"Esc",text:"cancel"}],select:[{key:"\u2191\u2193",text:"navigate"},{key:"Enter",text:"select"},{key:"Esc",text:"cancel"}],text:[{key:"Enter",text:"submit"},{key:"Esc",text:"cancel"}]};async function at(t){return Kt(qt.confirm),Wt(await kr(t))}async function tt(t){return Kt(qt.text),Wt(await Nr(t))}async function ut(t){return Kt(qt.select),Wt(await Fr({showInstructions:!1,...t}))}async function lt(t){return Kt(qt.multiselect),Wt(await Lr({showInstructions:!1,...t}))}var b={arg:m.magenta,cmd:m.cyan,default:m.blue,desc:m.white,flag:m.green,header:(t)=>m.bold(m.yellow(t)),hint:m.dim,name:(t)=>m.bold(m.cyan(t)),placeholder:m.magenta};class De{metadata;commands;globalArgs;constructor(t,e,r){this.metadata=t;this.commands=e;this.globalArgs=r}version(){return`${b.name(this.metadata.name)} ${b.hint(this.metadata.version??"0.0.0")}`}global(){let t=[],{name:e,bin:r,version:i,description:n}=this.metadata;if(t.push(""),t.push(`${b.name(e)}${i?` ${b.hint(`v${i}`)}`:""}`),n)t.push(b.desc(n));t.push(""),t.push(b.header("Usage:")),t.push(` ${b.cmd(r)} ${b.placeholder("[command]")} ${b.hint("[options]")}`),t.push(""),t.push(b.header("Commands:"));let s=Array.from(this.commands.values()).map((o)=>[` ${b.cmd(o.name)}`,b.desc(o.description)]);return t.push(...this.formatColumns(s)),t.push(""),t.push(b.header("Options:")),t.push(...this.formatArgDefs(this.globalArgs)),t.push(""),t.push(b.hint(`Run "${r} <command> --help" for command-specific options.`)),t.push(""),t.join(`
|
|
87
|
+
`)}command(t,e){let r=[],i=e??this.metadata.bin,n=`${b.cmd(i)} ${b.cmd(t.name)}`;r.push(""),r.push(`${b.name(t.name)} ${b.hint("-")} ${b.desc(t.description)}`),r.push(""),r.push(b.header("Usage:"));let s=this.formatPositionalUsage(t.positionals);if(t.hasSubcommands())r.push(` ${n} ${b.placeholder("<subcommand>")} ${b.hint("[options]")}`);else{let u=[n];if(s)u.push(s);u.push(b.hint("[options]")),r.push(` ${u.join(" ")}`)}if(t.prompts)r.push(` ${n} ${b.hint("- runs interactively")}`);if(r.push(""),t.hasSubcommands()){r.push(b.header("Subcommands:"));let u=t.getSubcommands().map((l)=>[` ${b.cmd(l.name)}`,b.desc(l.description)]);r.push(...this.formatColumns(u)),r.push("")}if(Object.entries(t.positionals).length>0)r.push(b.header("Arguments:")),r.push(...this.formatPositionalDefs(t.positionals)),r.push("");if(Object.entries(t.args).length>0)r.push(b.header("Options:")),r.push(...this.formatArgDefs(t.args)),r.push("");return r.join(`
|
|
88
|
+
`)}formatPositionalUsage(t){return Object.entries(t).map(([e,r])=>{let i=r.variadic?`${e}...`:e;return r.required?b.arg(`<${i}>`):b.arg(`[${i}]`)}).join(" ")}formatPositionalDefs(t){let e=Object.entries(t).map(([r,i])=>{let n=i.variadic?`${r}...`:r,s=b.desc(i.description??""),o=i.required?"":b.hint(" (optional)");return[` ${b.arg(n)}`,`${s}${o}`]});return this.formatColumns(e)}formatArgDefs(t){let e=[];for(let[r,i]of Object.entries(t)){let s=`${i.alias?`${b.flag(`-${i.alias}`)}, `:" "}${b.flag(`--${r}`)}`,o=b.desc(i.description??""),a=i.default!==void 0?b.hint(` (default: ${b.default(this.formatDefault(i))})`):"";e.push([` ${s}`,`${o}${a}`])}return this.formatColumns(e)}formatDefault(t){if(t.type==="string")return`"${t.default}"`;return String(t.default)}formatColumns(t){if(t.length===0)return[];let e=Math.max(...t.map(([i])=>this.stripAnsi(i).length)),r=2;return t.map(([i,n])=>{let s=e-this.stripAnsi(i).length+r;return`${i}${" ".repeat(s)}${n}`})}stripAnsi(t){return t.replace(/\x1b\[[0-9;]*m/g,"")}}var et=new Uint32Array(65536),Mn=(t,e)=>{let r=t.length,i=e.length,n=1<<r-1,s=-1,o=0,a=r,u=r;while(u--)et[t.charCodeAt(u)]|=1<<u;for(u=0;u<i;u++){let l=et[e.charCodeAt(u)],h=l|o;if(l|=(l&s)+s^s,o|=~(l|s),s&=l,o&n)a++;if(s&n)a--;o=o<<1|1,s=s<<1|~(h|o),o&=h}u=r;while(u--)et[t.charCodeAt(u)]=0;return a},On=(t,e)=>{let r=e.length,i=t.length,n=[],s=[],o=Math.ceil(r/32),a=Math.ceil(i/32);for(let d=0;d<o;d++)s[d]=-1,n[d]=0;let u=0;for(;u<a-1;u++){let d=0,y=-1,R=u*32,E=Math.min(32,i)+R;for(let C=R;C<E;C++)et[t.charCodeAt(C)]|=1<<C;for(let C=0;C<r;C++){let F=et[e.charCodeAt(C)],A=s[C/32|0]>>>C&1,x=n[C/32|0]>>>C&1,L=F|d,T=((F|x)&y)+y^y|F|x,P=d|~(T|y),k=y&T;if(P>>>31^A)s[C/32|0]^=1<<C;if(k>>>31^x)n[C/32|0]^=1<<C;P=P<<1|A,k=k<<1|x,y=k|~(L|P),d=P&L}for(let C=R;C<E;C++)et[t.charCodeAt(C)]=0}let l=0,h=-1,f=u*32,p=Math.min(32,i-f)+f;for(let d=f;d<p;d++)et[t.charCodeAt(d)]|=1<<d;let g=i;for(let d=0;d<r;d++){let y=et[e.charCodeAt(d)],R=s[d/32|0]>>>d&1,E=n[d/32|0]>>>d&1,C=y|l,F=((y|E)&h)+h^h|y|E,A=l|~(F|h),x=h&F;if(g+=A>>>i-1&1,g-=x>>>i-1&1,A>>>31^R)s[d/32|0]^=1<<d;if(x>>>31^E)n[d/32|0]^=1<<d;A=A<<1|R,x=x<<1|E,h=x|~(C|A),l=A&C}for(let d=f;d<p;d++)et[t.charCodeAt(d)]=0;return g},Un=(t,e)=>{if(t.length<e.length){let r=e;e=t,t=r}if(e.length===0)return t.length;if(t.length<=32)return Mn(t,e);return On(t,e)},Gr=(t,e)=>{let r=1/0,i=0;for(let n=0;n<e.length;n++){let s=Un(t,e[n]);if(s<r)r=s,i=n}return e[i]};function zt(t,e,r,i){let n=Gr(e,r);if(console.error(m.red(`Unknown ${t}: ${e}`)),n)console.error(m.yellow(`Did you mean "${n}"?`));console.error(`
|
|
89
|
+
Run "${i} --help" for usage.`),process.exit(1)}function Ct(t,e){let r=(n)=>n&&typeof n==="object";if(!r(t)||!r(e))return e;let i={...t};for(let n of Object.keys(e)){let s=i[n],o=e[n];if(Array.isArray(s)&&Array.isArray(o))i[n]=[...o];else if(r(s)&&r(o))i[n]=Ct(s,o);else i[n]=o}return i}function ke(t){return t==null?[]:Array.isArray(t)?t:[t]}function Vn(t,e,r,i){var n,s=t[e],o=~i.string.indexOf(e)?r==null||r===!0?"":String(r):typeof r==="boolean"?r:~i.boolean.indexOf(e)?r==="false"?!1:r==="true"||(t._.push((n=+r,n*0===0)?n:r),!!r):(n=+r,n*0===0)?n:r;t[e]=s==null?o:Array.isArray(s)?s.concat(o):[s,o]}function Yt(t,e){t=t||[],e=e||{};var r,i,n,s,o,a={_:[]},u=0,l=0,h=0,f=t.length;let p=e.alias!==void 0,g=e.unknown!==void 0,d=e.default!==void 0;if(e.alias=e.alias||{},e.string=ke(e.string),e.boolean=ke(e.boolean),p)for(r in e.alias){i=e.alias[r]=ke(e.alias[r]);for(u=0;u<i.length;u++)(e.alias[i[u]]=i.concat(r)).splice(u,1)}for(u=e.boolean.length;u-- >0;){i=e.alias[e.boolean[u]]||[];for(l=i.length;l-- >0;)e.boolean.push(i[l])}for(u=e.string.length;u-- >0;){i=e.alias[e.string[u]]||[];for(l=i.length;l-- >0;)e.string.push(i[l])}if(d){for(r in e.default)if(s=typeof e.default[r],i=e.alias[r]=e.alias[r]||[],e[s]!==void 0){e[s].push(r);for(u=0;u<i.length;u++)e[s].push(i[u])}}let y=g?Object.keys(e.alias):[];for(u=0;u<f;u++){if(n=t[u],n==="--"){a._=a._.concat(t.slice(++u));break}for(l=0;l<n.length;l++)if(n.charCodeAt(l)!==45)break;if(l===0)a._.push(n);else if(n.substring(l,l+3)==="no-"){if(s=n.substring(l+3),g&&!~y.indexOf(s))return e.unknown(n);a[s]=!1}else{for(h=l+1;h<n.length;h++)if(n.charCodeAt(h)===61)break;s=n.substring(l,h),o=n.substring(++h)||(u+1===f||(""+t[u+1]).charCodeAt(0)===45||t[++u]),i=l===2?[s]:s;for(h=0;h<i.length;h++){if(s=i[h],g&&!~y.indexOf(s))return e.unknown("-".repeat(l)+s);Vn(a,s,h+1<i.length||o,e)}}}if(d){for(r in e.default)if(a[r]===void 0)a[r]=e.default[r]}if(p)for(r in a){i=e.alias[r]||[];while(i.length>0)a[i.shift()]=a[r]}return a}function Gn(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function Hr(t){let e={alias:{},boolean:[],default:{},string:[]};for(let[r,i]of Object.entries(t)){if(i.type==="boolean")e.boolean.push(r);else e.string.push(r);if(i.alias)e.alias[i.alias]=r;let n=Gn(r);if(n!==r)e.alias[n]=r;if(i.default!==void 0)e.default[r]=i.default}return e}function Br(t,e){let r={...t};for(let[i,n]of Object.entries(e)){if(n.type!=="number")continue;let s=t[i];if(s===void 0||typeof s==="boolean")continue;let o=Number(s);if(Number.isNaN(o))throw Error(`Invalid number for --${i}: "${s}"`);r[i]=o}return r}function jr(t,e){let r=Hr(e),i=Yt(t,r),n=i._[0],s=n?t.indexOf(n):-1,{_:o,...a}=i,u=Br(a,e);return{command:n,flags:u,restArgs:s>=0?t.slice(s+1):[]}}function Le(t,e={}){let r=Hr(e),i=Yt(t,r),{_:n,...s}=i;return{args:Br(s,e),rawPositionals:n}}function Fe(t,e){let r={},i=Object.entries(e);for(let[n,[s,o]]of i.entries())r[s]=o.variadic?t.slice(n):t[n];return r}function Wr(t,e){for(let[r,i]of Object.entries(e)){if(!i.required)continue;let n=t[r];if(Array.isArray(n)?n.length===0:!n)return`Missing required argument: <${r}${i.variadic?"...":""}>`}return null}var Ne="__exit__";class ht{command;env;prefix;options;constructor(t,e,r,i={}){this.command=t;this.env=e;this.prefix=r;this.options=i}get commandPath(){return this.prefix?`${this.prefix} ${this.command.name}`:this.command.name}async route(t,e){if(e)await this.routeInteractive();else await this.routeDirect(t)}async routeDirect(t){let[e,...r]=t;if(e&&this.command.hasSubcommands()){let i=this.command.getSubcommand(e);if(i){await this.handleSubcommandRoute(i,r);return}if(!e.startsWith("-")){this.handleUnknownSubcommand(e);return}}await this.executeCommand(t)}handleUnknownSubcommand(t){let e=this.command.getSubcommands().map((r)=>r.name);zt("subcommand",t,e,this.commandPath)}async handleSubcommandRoute(t,e){await new ht(t,this.env,this.commandPath).route(e,!1)}async executeCommand(t){if(this.isHelpRequest(t)){this.printHelp(this.command);return}if(this.command.hasSubcommands()&&!this.command.execute){this.printHelp(this.command);return}if(!this.command.execute)return;let{args:r,rawPositionals:i}=Le(t,this.command.args),n=Fe(i,this.command.positionals),s=Wr(n,this.command.positionals);if(s)$.error(s),console.error(`
|
|
90
|
+
Run "${this.commandPath} --help" for usage.`),process.exit(1);let o=this.command.prompts&&i.length===0,a=this.buildContext(n,r,o);await this.command.execute(a)}async routeInteractive(){if(!this.command.hasSubcommands()){await this.executeInteractive();return}await this.runSubcommandMenu()}async executeInteractive(){let{args:t}=Le([],this.command.args),e=Fe([],this.command.positionals),r=this.buildContext(e,t,!0);await this.command.execute?.(r)}async runSubcommandMenu(){while(!0){let t=await this.promptSubcommandSelectionOrBack();if(t===null)return;if(t===Ne){this.options.onExit?.();return}let e=this.command.getSubcommand(t);if(e)await this.executeSubcommand(e)}}async promptSubcommandSelectionOrBack(){try{return await this.promptSubcommandSelection()}catch(t){if(t instanceof q){if(this.options.isRoot)this.options.onExit?.();return null}throw t}}async executeSubcommand(t){try{await new ht(t,this.env,this.commandPath).route([],!0)}catch(e){if(e instanceof q)return;if(e instanceof v){if($.warn(m.yellow(e.message)),e.hint)$.info(m.dim(e.hint));return}throw e}}promptSubcommandSelection(){let{isRoot:t}=this.options,e=t?{hint:this.env.cli.exitHint,label:this.env.cli.exitLabel??"Exit",value:Ne}:{hint:"Return to previous menu",label:"Back",value:Ne};return ut({message:t?this.env.cli.promptMessage??"Select:":`${this.command.name}:`,options:[...this.command.getSubcommands().map((r)=>({hint:r.description,label:r.name,value:r.name})),e]})}buildContext(t,e,r){return{...this.env,args:e,interactive:r,positionals:t}}isHelpRequest(t){return t.includes("--help")||t.includes("-h")}printHelp(t){let e=t===this.command?this.prefix:this.commandPath;console.log(this.env.formatHelp(t,e))}}var Hn={clearOnStart:!0,exitHint:"Close the CLI",exitLabel:"Exit",goodbyeMessage:"Goodbye!",name:"CLI",promptMessage:"What would you like to do?"};class Me{commands=new Map;metadata;configManager;help;bin;globalArgs={help:{alias:"h",description:"Show help",type:"boolean"},interactive:{alias:"i",description:"Enable interactive mode",type:"boolean"},version:{alias:"v",description:"Show version",type:"boolean"}};constructor(t,e){this.configManager=t,this.metadata={...Hn,...e},this.bin=this.metadata.bin??this.metadata.name,this.init(),this.help=new De({bin:this.bin,description:this.metadata.description,name:this.metadata.name,version:this.metadata.version},this.commands,this.globalArgs)}registerCommands(t){for(let e of t)e.init?.(),this.commands.set(e.name,e)}async run(t=process.argv.slice(2)){let{command:e,flags:r,restArgs:i}=jr(t,this.globalArgs);if(r.version&&!e)return console.log(this.help.version());if(r.interactive&&!e)return this.runInteractive();if(!e)return console.log(this.help.global());if(e==="help")return this.printHelpFor(i[0]);await this.runDirect(e,i,!!r.help)}printHelpFor(t){if(!t)return console.log(this.help.global());let e=this.commands.get(t);if(!e)return this.handleUnknownCommand(t);console.log(this.help.command(e))}async runInteractive(){this.showIntro();let t=this.createVirtualRootCommand(),e={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)},r=new ht(t,e,this.bin,{isRoot:!0,onExit:()=>this.exit()});try{await r.route([],!0)}catch(i){this.handleError(i)}}createVirtualRootCommand(){return{description:this.metadata.description,getSubcommand:(t)=>this.commands.get(t),getSubcommands:()=>Array.from(this.commands.values()),hasSubcommands:()=>!0,name:this.metadata.name}}exit(){Bt(this.metadata.goodbyeMessage),process.exit(0)}async runDirect(t,e,r){let i=this.commands.get(t);if(!i)return this.handleUnknownCommand(t);let n=e.length>0&&!e[0]?.startsWith("-");if(r&&!n)return console.log(this.help.command(i));try{let s={cli:this.metadata,config:this.configManager,formatHelp:this.help.command.bind(this.help)};await new ht(i,s,this.bin).route(e,!1)}catch(s){this.handleError(s)}}showIntro(){if(this.metadata.clearOnStart)console.clear();let t=this.metadata.version?` v${this.metadata.version}`:"";Ht(`${m.bgCyan(m.black(` ${this.metadata.name}${t} `))}`)}handleUnknownCommand(t){let e=Array.from(this.commands.keys());zt("command",t,e,this.bin)}handleError(t){if(this.metadata.onError?.(t))return;if(t instanceof q)process.exit(0);if(t instanceof v){if($.warn(m.yellow(t.message)),t.hint)$.info(m.dim(t.hint));process.exit(0)}if(t instanceof Error)$.error(m.red(t.message)),process.exit(1);console.error(m.red("Error:"),t),process.exit(1)}}class xt{args={};positionals={};prompts=!1;subcommands=new Map;registerSubcommands(t){for(let e of t)e.init?.(),this.subcommands.set(e.name,e)}hasSubcommands(){return this.subcommands.size>0}getSubcommand(t){return this.subcommands.get(t)}getSubcommands(){return Array.from(this.subcommands.values())}}function st(t){return t}function M(t){return t}import ft from"fs";import Kr from"path";class Oe{config;configPath;defaultConfig;constructor(t,e){this.configPath=Kr.resolve(t),this.defaultConfig=e,this.config=this.loadConfig()}get(t){return this.config[t]}set(t,e){this.config[t]=e,this.save()}delete(t){delete this.config[t],this.save()}exists(){return ft.existsSync(this.configPath)}getAll(){return Ct({},this.config)}save(t){if(t)this.config={...t};this.ensureDirectoryExists();try{ft.writeFileSync(this.configPath,JSON.stringify(this.config,null,2))}catch(e){console.error(`Failed to save config to ${this.configPath}:`,e)}}ensureDirectoryExists(){let t=Kr.dirname(this.configPath);if(!ft.existsSync(t))try{ft.mkdirSync(t,{recursive:!0})}catch(e){console.error(`Failed to create config directory at ${t}:`,e)}}loadConfig(){if(!ft.existsSync(this.configPath))return{...this.defaultConfig};try{let t=ft.readFileSync(this.configPath,"utf-8"),e=JSON.parse(t);return Ct({...this.defaultConfig},e)}catch{return console.warn(`Config file corrupted at ${this.configPath}. Using defaults.`),{...this.defaultConfig}}}}var qr="0.8.0";class I extends xt{}import{existsSync as _t}from"fs";import{cp as Jn,link as Xn,mkdir as Ge,readdir as si,readFile as He,readlink as Zn,rm as Be,symlink as Qn,unlink as oi,writeFile as ts}from"fs/promises";import{join as _,resolve as Qt}from"path";var Jt="hydra";var zr=".hydra/config.json",ct=".hydra/shared",Rt=".hydra/runners",St="default",Yr={profiles:{}},Jr=!1,Xr=24,Zr=7,Qr=["logs","shared"];var jn=new Set(["github.com","www.github.com"]);var ti=/\.git$/;function pt(t){let e;try{e=new URL(t)}catch{throw Error(`Invalid GitHub URL: ${t}`)}if(e.protocol!=="https:"&&e.protocol!=="http:")throw Error(`Invalid GitHub URL (expected http(s)): ${t}`);if(!jn.has(e.hostname))throw Error(`Invalid GitHub URL (host must be github.com): ${t}`);let r=e.pathname.split("/").filter(Boolean);if(r.length===1){let i=r[0]?.replace(ti,"");if(!i)throw Error(`Invalid GitHub URL: ${t}`);return{kind:"org",org:i}}if(r.length===2){let i=r[0],n=r[1]?.replace(ti,"");if(!i||!n)throw Error(`Invalid GitHub URL: ${t}`);return{kind:"repo",owner:i,repo:n}}throw Error(`Invalid GitHub URL (expected github.com/<owner>/<repo> or github.com/<org>): ${t}`)}function Xt(t){return t.kind==="repo"?`${t.owner}/${t.repo}`:t.org}import{existsSync as Wn}from"fs";import{readdir as Kn,stat as qn}from"fs/promises";import{join as zn}from"path";var It="_diag",ei={runner:/^Runner_.+\.log$/,worker:/^Worker_.+\.log$/},ri=1024,ii=["B","KB","MB","GB"],Yn=1;function ni(t){if(ei.worker.test(t))return"worker";if(ei.runner.test(t))return"runner";return null}function Zt(t){return[...t].sort((e,r)=>r.mtime.getTime()-e.mtime.getTime())}async function Pt(t){if(!Wn(t))return[];let e=await Kn(t,{withFileTypes:!0}),r=[];for(let i of e){if(!i.isFile())continue;let n=ni(i.name);if(!n)continue;let s=zn(t,i.name),o=await qn(s);r.push({mtime:o.mtime,name:i.name,path:s,size:o.size,type:n})}return Zt(r)}function Ue(t,e){let r=t.find((n)=>n.type===e);if(r)return{fallback:!1,file:r};let i=t[0];return i?{fallback:!0,file:i}:null}function Ve(t,e){if(e<=0)return"";let r=t.endsWith(`
|
|
91
|
+
`)?t.slice(0,-1):t;if(r==="")return"";return r.split(`
|
|
92
|
+
`).slice(-e).join(`
|
|
93
|
+
`)}function mt(t){let e=t,r=0;while(e>=ri&&r<ii.length-1)e/=ri,r++;return`${r===0?String(e):e.toFixed(Yn)} ${ii[r]??"B"}`}var ai="actions/runner",es={linux:"linux-x64",osx:"osx-arm64",windows:"win-x64"},ui=["bin"],li=["externals"];class te{profile;sharedPath=null;constructor(t){this.profile=t}async download(){let t=es[this.profile.os],e=await this.getLatestVersion(),r=_(ct,"github",e);if(_t(r))return this.sharedPath=r,{path:r,version:e};await Ge(r,{recursive:!0});let i=`actions-runner-${t}-${e}.tar.gz`,n=_(r,i),s=`https://github.com/${ai}/releases/download/v${e}/${i}`;return await Bun.$`curl -sL -o ${n} ${s}`,await Bun.$`tar xzf ${n} -C ${r}`,await oi(n),this.sharedPath=r,{path:r,version:e}}async create(t){let e=await this.ensureDownloaded(),r=[];for(let i of t){let n=_(this.profile.directory,i);await this.setupRunnerDir(e,n),await this.registerRunner(n,i),r.push({directory:n,id:i,name:i,status:"registered"})}return r}async remove(t){for(let e of t){let r=_(this.profile.directory,e);if(!_t(_(r,".runner")))continue;let i=await this.fetchRemovalToken(r);await Bun.$`bash ./config.sh remove --token ${i}`.cwd(r).quiet().nothrow()}}async start(t){for(let e of t){let r=_(this.profile.directory,e),i=await this.readPidFile(r);if(i&&this.isProcessRunning(i))continue;let n=Bun.spawn(["bash","./run.sh"],{cwd:Qt(r),stderr:"pipe",stdout:"pipe"});n.unref(),await this.writePidFile(r,n.pid)}}async stop(t){for(let e of t){let r=_(this.profile.directory,e);if(!await this.readPidFile(r))continue;let n=Qt(r);await Bun.$`pkill -f ${n}`.quiet().nothrow(),await this.removePidFile(r)}}async list(){let t=this.profile.directory;if(!_t(t))return[];let e=await si(t,{withFileTypes:!0}),r=[];for(let i of e){if(!i.isDirectory())continue;let n=_(t,i.name);r.push(await this.getRunnerStatus(n,i.name))}return r}async currentVersion(t){let e=_(this.profile.directory,t);return this.detectVersion(e)}async logFiles(t){return Pt(_(this.profile.directory,t,It))}async update(t){let e=await this.ensureDownloaded();for(let r of t){let i=_(this.profile.directory,r);await this.removeRunnerBinaries(i),await this.setupRunnerDir(e,i)}}async getRunnerStatus(t,e){let r=await this.readRunnerName(t),i=await this.readPidFile(t),n=i!==null&&this.isProcessRunning(i),s="unknown";if(n)s="running";else if(_t(_(t,".runner")))s="registered";return{directory:t,id:e,name:r,pid:n?i:void 0,status:s}}async ensureDownloaded(){if(this.sharedPath)return this.sharedPath;let{path:t}=await this.download();return t}async setupRunnerDir(t,e){await Ge(e,{recursive:!0});for(let r of ui)await this.hardLinkDir(_(t,r),_(e,r));for(let r of li){let i=Qt(t,r),n=_(e,r);if(!_t(n))await Qn(i,n)}for(let r of["*.sh","*.sh.template"]){let i=await Array.fromAsync(new Bun.Glob(r).scan(t));for(let n of i)await Jn(_(t,n),_(e,n))}}async registerRunner(t,e){let r=await this.fetchRegistrationToken(),i=["--url",this.profile.url,"--token",r,"--name",e,"--unattended"];if(this.profile.labels)i.push("--labels",this.profile.labels);if(this.profile.runnerGroup)i.push("--runnergroup",this.profile.runnerGroup);await Bun.$`bash ./config.sh ${i}`.cwd(t).quiet()}async fetchRegistrationToken(){return this.fetchRunnerToken(pt(this.profile.url),"registration-token")}async fetchRemovalToken(t){let e=await He(_(t,".runner"),"utf-8"),i=JSON.parse(this.stripBom(e)).gitHubUrl;if(!i)throw Error("Cannot determine GitHub URL from runner config");return this.fetchRunnerToken(pt(i),"remove-token")}async fetchRunnerToken(t,e){let r=t.kind==="repo"?`repos/${t.owner}/${t.repo}/actions/runners/${e}`:`orgs/${t.org}/actions/runners/${e}`,i=t.kind==="repo"?"gh needs admin access to the repository":"gh needs the admin:org scope",n=await Bun.$`gh api ${r} --method POST --jq .token`.quiet().nothrow();if(n.exitCode!==0){let o=n.stderr.toString().trim();throw Error(`gh api ${r} failed for ${Xt(t)} (${i})${o?`: ${o}`:""}`)}let s=n.stdout.toString().trim();if(!s)throw Error(`Failed to fetch ${e} for ${Xt(t)}`);return s}async getLatestVersion(){return(await Bun.$`gh api repos/${ai}/releases/latest --jq .tag_name`.quiet()).stdout.toString().trim().replace(/^v/,"")}pidFilePath(t){return Qt(t,".pid")}async writePidFile(t,e){await ts(this.pidFilePath(t),String(e))}async readPidFile(t){try{let e=await He(this.pidFilePath(t),"utf-8");return Number.parseInt(e.trim(),10)}catch{return null}}async removePidFile(t){try{await oi(this.pidFilePath(t))}catch{}}async readRunnerName(t){try{let e=await He(_(t,".runner"),"utf-8");return JSON.parse(this.stripBom(e)).agentName??"unknown"}catch{return"unknown"}}async hardLinkDir(t,e){await Ge(e,{recursive:!0});let r=await si(t,{withFileTypes:!0});for(let i of r){let n=_(t,i.name),s=_(e,i.name);if(i.isDirectory())await this.hardLinkDir(n,s);else await Xn(n,s)}}async detectVersion(t){try{return(await Zn(_(t,"externals"))).match(/github\/([^/]+)/)?.[1]??null}catch{return null}}async removeRunnerBinaries(t){for(let e of ui)await Be(_(t,e),{force:!0,recursive:!0});for(let e of li)await Be(_(t,e),{force:!0});for(let e of["*.sh","*.sh.template"]){let r=await Array.fromAsync(new Bun.Glob(e).scan(t));for(let i of r)await Be(_(t,i),{force:!0})}}stripBom(t){return t.replace(/^\uFEFF/,"")}isProcessRunning(t){try{return process.kill(t,0),!0}catch{return!1}}}import{existsSync as We}from"fs";import{readdir as Ke,readFile as rs,readlink as is,rm as qe,stat as ns}from"fs/promises";import{join as ot}from"path";var ci="_work",ss="externals",os=".pid",as="github",us=/github\/([^/]+)/,ls=["runner","worker"],cs=24,pi=3600000,je=10;function ee(t){return{auto:t?.auto??Jr,intervalHours:t?.intervalHours??Xr,lastRun:t?.lastRun,olderThanDays:t?.olderThanDays??Zr,targets:t?.targets??Qr}}function mi(t,e){return t-e*cs*pi}function ze(t,e){if(!t.lastRun)return!0;let r=Date.parse(t.lastRun);if(Number.isNaN(r))return!0;return e-r>=t.intervalHours*pi}function di(t,e){let r=Zt(t),i=new Set;for(let n of ls){let s=r.find((o)=>o.type===n);if(s)i.add(s.path)}return r.filter((n)=>!i.has(n.path)&&n.mtime.getTime()<e)}function hi(t){return[...t].sort(fs)[0]??null}function fi(t,e){let r=hi(t),i=new Set(e);return t.filter((n)=>n!==r&&!i.has(n))}function gi(t){return t.match(us)?.[1]??null}function re(t){return Object.values(t).reduce((e,r)=>e+r.freedBytes,0)}async function yi(t){try{let e=await rs(ot(t,os),"utf-8"),r=Number.parseInt(e.trim(),je);if(Number.isNaN(r))return!1;return process.kill(r,0),!0}catch{return!1}}async function ie(t){if(!We(t))return 0;let e=await Ke(t,{withFileTypes:!0}),r=0;for(let i of e){if(i.isSymbolicLink())continue;let n=ot(t,i.name);if(i.isDirectory()){r+=await ie(n);continue}if(i.isFile()){let s=await ns(n);r+=s.size}}return r}async function ne(t){let e=mi(t.now,t.olderThanDays),r={};for(let i of t.targets)switch(i){case"logs":r.logs=await ps(t.entries,e,t.dryRun);break;case"work":r.work=await ms(t.entries,t.dryRun);break;case"shared":r.shared=await ds(t.entries,t.dryRun,t.sharedDir);break}return r}async function ps(t,e,r){let i={freedBytes:0,removed:0,skipped:[]};for(let n of t){let s=await Pt(ot(n.directory,It));for(let o of di(s,e)){if(!r)await qe(o.path,{force:!0});i.removed++,i.freedBytes+=o.size}}return i}async function ms(t,e){let r={freedBytes:0,removed:0,skipped:[]};for(let i of t){if(await yi(i.directory)){r.skipped.push(i.id);continue}let n=ot(i.directory,ci);if(!We(n))continue;let s=await Ke(n);if(s.length===0)continue;if(r.freedBytes+=await ie(n),r.removed+=s.length,e)continue;for(let o of s)await qe(ot(n,o),{force:!0,recursive:!0})}return r}async function ds(t,e,r){let i={freedBytes:0,removed:0,skipped:[]},n=r??ot(ct,as);if(!We(n))return i;let o=(await Ke(n,{withFileTypes:!0})).filter((u)=>u.isDirectory()).map((u)=>u.name),a=await hs(t);for(let u of fi(o,a)){let l=ot(n,u);if(i.freedBytes+=await ie(l),i.removed++,!e)await qe(l,{force:!0,recursive:!0})}return i}async function hs(t){let e=[];for(let r of t)try{let i=await is(ot(r.directory,ss)),n=gi(i);if(n)e.push(n)}catch{}return e}function fs(t,e){let r=t.split(".").map((s)=>Number.parseInt(s,je)),i=e.split(".").map((s)=>Number.parseInt(s,je)),n=Math.max(r.length,i.length);for(let s=0;s<n;s++){let o=r[s]??0,a=i[s]??0,u=Number.isNaN(o)?0:o,l=Number.isNaN(a)?0:a;if(u!==l)return l-u}return 0}function O(t){switch(t.provider){case"github":return new te(t);default:throw Error(`Runner provider "${t.provider}" is not yet implemented`)}}var $i=0,gs={logs:"file(s)",shared:"version(s)",work:"item(s)"},ys=st({days:{alias:"d",default:$i,description:"Prune logs older than this many days (default from config)",type:"number"},dryRun:{alias:"n",default:!1,description:"List what would be deleted without deleting",type:"boolean"},logs:{alias:"l",default:!1,description:"Prune old _diag log files",type:"boolean"},shared:{alias:"s",default:!1,description:"Remove unused shared runner versions",type:"boolean"},work:{alias:"w",default:!1,description:"Delete _work contents of stopped runners",type:"boolean"},yes:{alias:"y",default:!1,description:"Skip confirmation prompts",type:"boolean"}});class se extends I{name="cleanup";description="Free disk space used by logs, job workspaces, and old runner versions";args=ys;async execute(t){let e=t.config.get("profiles");if(Object.keys(e).length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let r=ee(t.config.get("cleanup")),i=this.explicitTargets(t),n=i.length>0?i:r.targets,s=t.args.days>$i?t.args.days:r.olderThanDays;if(n.includes("work")&&!t.args.dryRun&&!t.args.yes&&t.interactive){if(!await at({message:"Delete _work contents (checkouts and caches) of stopped runners?"}))n=n.filter((u)=>u!=="work")}let o=await ne({dryRun:t.args.dryRun,entries:t.config.get("runners")??[],now:Date.now(),olderThanDays:s,targets:n});if(this.printReport(o,t.args.dryRun),t.args.dryRun)return;t.config.set("cleanup",{...t.config.get("cleanup"),lastRun:new Date().toISOString()})}explicitTargets(t){let e=[];if(t.args.logs)e.push("logs");if(t.args.work)e.push("work");if(t.args.shared)e.push("shared");return e}printReport(t,e){let r=[];for(let[s,o]of Object.entries(t)){if(!o)continue;let a=gs[s],u=mt(o.freedBytes),l=e?`would remove ${o.removed} ${a}, ${u}`:`removed ${o.removed} ${a}, freed ${u}`;if(r.push(`${m.bold(s)}: ${o.removed>0?l:m.dim("nothing to do")}`),o.skipped.length>0)r.push(m.dim(` skipped running runner(s): ${o.skipped.join(", ")}`))}if(r.length===0){$.info(m.dim("Nothing to clean."));return}let i=re(t),n=e?"Would free":"Freed";r.push(m.dim(`${n} ${mt(i)} total`)),$.info(r.join(`
|
|
94
|
+
`))}}async function Et(t){try{let e=ee(t.config.get("cleanup"));if(!e.auto)return;if(!ze(e,Date.now()))return;let r=await ne({dryRun:!1,entries:t.config.get("runners")??[],now:Date.now(),olderThanDays:e.olderThanDays,targets:e.targets});t.config.set("cleanup",{...t.config.get("cleanup"),lastRun:new Date().toISOString()});let i=re(r);if(i>0)$.info(m.dim(`Auto cleanup freed ${mt(i)}`))}catch(e){let r=e instanceof Error?e.message:String(e);$.warn(m.yellow(`Auto cleanup failed: ${r}`))}}import{join as $s}from"path";function gt(t,e){if(t.length===0)return e;for(let r of t)if(!e.includes(r))throw new v(`Runner "${r}" not found`);return t}function V(t,e){let r=t.get("profiles");if(Object.keys(r).length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=e??t.get("defaultProfile")??St,n=r[i];if(!n)throw new v(`Profile "${i}" not found`);return{name:i,profile:n}}async function K(t){let e=t.get("profiles"),r=Object.keys(e);if(r.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");if(r.length===1)return r[0];return ut({message:"Select profile",options:r.map((i)=>({label:i,value:i,hint:e[i]?.url}))})}var vs=M({profile:{description:"Profile name"},count:{description:"Number of runners to create (overrides profile)"}});class oe extends I{name="create";description="Create and register runners";positionals=vs;async execute(t){let{name:e,profile:r}=t.interactive?V(t.config,await K(t.config)):V(t.config,t.positionals.profile),i=t.interactive?await this.promptCount(r.numberOfMachines):t.positionals.count?Number.parseInt(t.positionals.count,10):r.numberOfMachines;if(!i||i<1)throw new v("Runner count must be at least 1");let n=O(r),s=B();s.start("Downloading runner binary...");let{version:o}=await n.download();s.stop(`Runner v${o} ready`);let a=t.config.get("runners")??[],u=a.filter((d)=>d.profile===e),l=i-u.length;if(l<=0){$.warn(`Already have ${u.length} runner(s) for profile "${e}". Nothing to create.`);return}let h=new Set(a.map((d)=>d.id)),f=1;for(let d=0;d<l;){let y=`${r.name}-${f++}`;if(h.has(y))continue;d++,s.start(`Registering ${y}...`),await n.create([y]),s.stop(`${m.green("+")} ${y}`),a.push({createdAt:new Date().toISOString(),directory:$s(r.directory,y),id:y,name:y,profile:e,provider:r.provider,url:r.url})}t.config.set("runners",a);let g=e===t.config.get("defaultProfile")?"":` ${e}`;$.info(`${m.green("Created")} ${l} runner(s) for "${e}". Run ${m.green(`hydra start${g}`)} to start them.`)}async promptCount(t){let e=await tt({initialValue:String(t),message:"Number of runners to create",validate:(r)=>{let i=Number.parseInt(r??"",10);if(Number.isNaN(i)||i<1)return"Must be a positive number";return}});return Number.parseInt(e,10)}}import{existsSync as vi}from"fs";import{mkdir as bi}from"fs/promises";var bs=M({url:{description:"GitHub repository or organization URL"}}),ws=st({force:{alias:"f",default:!1,description:"Overwrite existing config",type:"boolean"},labels:{alias:"l",description:"Comma-separated runner labels",type:"string"},name:{alias:"n",description:"Base name for runners",type:"string"},profile:{alias:"p",description:"Profile name",type:"string"},runners:{alias:"c",description:"Number of runners to create",type:"number"}});class ae extends I{name="init";description="Initialize Hydra runner manager";positionals=bs;args=ws;prompts=!0;async execute(t){let e=t.interactive?await this.promptProfileName(t):t.args.profile??St,r=!t.config.exists();if(!r&&t.config.get("profiles")[e]&&!t.args.force){if(!t.interactive)throw new v(`Profile "${e}" already exists. Use --force to overwrite.`);if(!await at({initialValue:!1,message:`Profile "${e}" already exists. Overwrite?`}))return}await this.ensureDirectories();let n=t.interactive?await this.runInitForm():this.buildProfileFromArgs(t),s=r?{}:{...t.config.get("profiles")};if(s[e]=n,t.config.set("profiles",s),!t.config.get("defaultProfile"))t.config.set("defaultProfile",e);dt([`${m.dim("Profile:")} ${e}`,`${m.dim("URL:")} ${n.url}`,`${m.dim("Runners:")} ${n.numberOfMachines}`,`${m.dim("Name:")} ${n.name}`,n.labels?`${m.dim("Labels:")} ${n.labels}`:"","",`Run ${m.green(`${Jt} create${e!==t.config.get("defaultProfile")?` ${e}`:""}`)} to provision runners.`].filter(Boolean).join(`
|
|
95
|
+
`),m.green(r?"Hydra initialized":`Profile "${e}" added`))}async promptProfileName(t){return tt({initialValue:t.args.profile??St,message:"Profile name"})}async ensureDirectories(){if(!vi(ct))await bi(ct,{recursive:!0});if(!vi(Rt))await bi(Rt,{recursive:!0})}async runInitForm(){let t=await Gt({url:()=>tt({message:"GitHub repository or organization URL",placeholder:"https://github.com/owner/repo",validate:(e)=>{if(!e)return"URL is required";try{pt(e)}catch{return"Must be a GitHub repository or organization URL (https://github.com/<owner>/<repo> or https://github.com/<org>)"}return}}),name:()=>tt({initialValue:"runner",message:"Base name for runners",placeholder:"runner"}),runners:()=>tt({initialValue:"1",message:"Number of runners",placeholder:"1",validate:(e)=>{if(!e)return"Must be a positive number";let r=Number.parseInt(e,10);if(Number.isNaN(r)||r<1)return"Must be a positive number";return}}),labels:()=>tt({message:"Additional labels (comma-separated, optional)",placeholder:"self-hosted,macOS,ARM64"})},{onCancel:()=>{throw new q}});return{directory:Rt,labels:t.labels||void 0,name:t.name,numberOfMachines:Number.parseInt(t.runners,10)||1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:t.url}}buildProfileFromArgs(t){if(!t.positionals.url)throw new v("URL is required","Usage: hydra init <url>");return this.validateUrl(t.positionals.url),this.validateRunnerCount(t.args.runners),{directory:Rt,labels:t.args.labels,name:t.args.name??"runner",numberOfMachines:t.args.runners??1,os:this.detectOs(),overwrite:!1,provider:"github",run:!1,url:t.positionals.url}}validateUrl(t){try{pt(t)}catch(e){throw new v(e instanceof Error?e.message:`Invalid GitHub URL: ${t}`,"Expected https://github.com/<owner>/<repo> or https://github.com/<org>")}}validateRunnerCount(t){if(t!==void 0&&t<1)throw new v("Runner count must be at least 1")}detectOs(){let t=process.platform;if(t==="darwin")return"osx";if(t==="win32")return"windows";return"linux"}}import{existsSync as Cs}from"fs";import{readFile as xs}from"fs/promises";var Rs=100,Ss={runner:"runner daemon log",worker:"job log"},Is=st({lines:{alias:"n",default:Rs,description:"Number of lines to tail",type:"number"},list:{alias:"l",default:!1,description:"List available log files instead of printing content",type:"boolean"},open:{alias:"o",default:!1,description:"Open the log file in $EDITOR instead of printing",type:"boolean"},runner:{alias:"r",default:!1,description:"Show the runner daemon log instead of the latest job log",type:"boolean"}}),Ps=M({id:{description:"Runner ID"}});class ue extends I{name="logs";description="Inspect logs of the latest jobs";args=Is;positionals=Ps;async execute(t){let e=t.config.get("runners")??[];if(e.length===0)throw new v("No runners found","Run hydra create to provision runners");let r=await this.resolveEntry(t,e),i=t.config.get("profiles")[r.profile];if(!i)throw new v(`Profile "${r.profile}" not found for runner "${r.id}"`,"Run hydra init to set it up");if(!Cs(r.directory))throw new v(`Runner directory not found: ${r.directory}`,"Run hydra create to provision this runner");let s=await O(i).logFiles(r.id);if(s.length===0)this.noLogs(r.id);if(t.args.list){this.printList(r,s);return}let o=this.selectFile(t,r,s);if(t.args.open){await this.openFile(o);return}await this.printTail(r,o,t.args.lines)}async resolveEntry(t,e){let r=t.positionals.id;if(r){let n=e.find((s)=>s.id===r);if(!n)throw new v(`Runner "${r}" not found`,`Known runners: ${e.map((s)=>s.id).join(", ")}`);return n}if(t.interactive)return ut({message:"Select runner",options:e.map((n)=>({hint:n.profile,label:n.name,value:n}))});let i=e[0];if(e.length===1&&i)return i;throw new v("Multiple runners found",`Pass a runner id: hydra logs <id> (${e.map((n)=>n.id).join(", ")})`)}selectFile(t,e,r){if(t.args.runner){let n=r.find((s)=>s.type==="runner");if(!n)throw new v(`No runner daemon logs found for "${e.id}"`,"Start the runner first: hydra start");return n}let i=Ue(r,"worker");if(!i)this.noLogs(e.id);if(i.fallback)$.warn(m.yellow("No job (Worker) logs yet; showing the runner daemon log instead"));return i.file}noLogs(t){throw new v(`No logs found for runner "${t}"`,"Logs appear once the runner has started; run hydra start")}printList(t,e){let r=[`${m.bold(t.name)} ${m.dim(t.directory)}`];for(let i of e){let n=i.type==="worker"?m.green("worker"):m.blue("runner");r.push(` ${n} ${i.name} ${m.dim(`${i.mtime.toISOString()} \xB7 ${mt(i.size)}`)}`)}$.info(r.join(`
|
|
96
|
+
`))}async printTail(t,e,r){let i=await xs(e.path,"utf-8"),n=[`${m.bold(t.name)} ${m.dim(Ss[e.type])}`,m.dim(e.path),m.dim(`Last modified: ${e.mtime.toISOString()}`)];$.info(n.join(`
|
|
97
|
+
`)),console.log(Ve(i,r))}async openFile(t){let e=(process.env.EDITOR??"").split(" ").filter(Boolean),r=e[0];if(r){await Bun.spawn([r,...e.slice(1),t.path],{stderr:"inherit",stdin:"inherit",stdout:"inherit"}).exited;return}if(process.platform==="darwin"){await Bun.$`open ${t.path}`.quiet();return}throw new v("No editor configured","Set $EDITOR to open log files")}}var _s=M({name:{description:"Profile name to set as default"}});class Ye extends I{name="default";description="Set the default profile";positionals=_s;async execute(t){let e=t.interactive?await K(t.config):t.positionals.name;if(!e)throw new v("Profile name is required","Usage: hydra profile default <name>");let{name:r}=V(t.config,e);if(t.config.get("defaultProfile")===r){$.info(`"${r}" is already the default profile.`);return}t.config.set("defaultProfile",r),$.info(`${m.green("Default profile set to")} "${r}".`)}}class Je extends I{name="list";description="List all profiles";async execute(t){let e=t.config.get("profiles"),r=Object.keys(e);if(r.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=t.config.get("runners")??[],n=t.config.get("defaultProfile");for(let s of r){let o=e[s],u=await O(o).list(),l=i.filter((y)=>y.profile===s),h=new Set(u.filter((y)=>y.status==="running").map((y)=>y.id)),f=l.filter((y)=>h.has(y.id)).length,p=s===n,g=[`${m.dim("URL:")} ${o.url}`,`${m.dim("Provider:")} ${o.provider}`,`${m.dim("OS:")} ${o.os}`,`${m.dim("Name:")} ${o.name}`,`${m.dim("Runners:")} ${l.length}/${o.numberOfMachines} created, ${m.green(`${f} running`)}`];if(o.labels)g.push(`${m.dim("Labels:")} ${o.labels}`);let d=p?`${s} ${m.dim("(default)")}`:s;dt(g.join(`
|
|
98
|
+
`),d)}$.info(m.dim(`${r.length} profile(s)`))}}import{rm as Es}from"fs/promises";import{join as As}from"path";var Ts=M({name:{description:"Profile name to remove"}});class Xe extends I{name="remove";description="Remove a profile";positionals=Ts;async execute(t){let e=t.interactive?await K(t.config):t.positionals.name;if(!e)throw new v("Profile name is required","Usage: hydra profile remove <name>");let{profile:r}=V(t.config,e),i=t.config.get("runners")??[],n=i.filter((u)=>u.profile===e);if(n.length>0){if(!await at({initialValue:!0,message:`This will stop and remove ${n.length} runner(s). Continue?`}))return;await this.removeRunners(r,n.map((h)=>h.id));let l=i.filter((h)=>h.profile!==e);t.config.set("runners",l)}let{[e]:s,...o}=t.config.get("profiles");if(t.config.set("profiles",o),t.config.get("defaultProfile")===e){let u=Object.keys(o);t.config.set("defaultProfile",u[0])}$.info(`${m.green("Removed")} profile "${e}".`)}async removeRunners(t,e){let r=O(t),i=B();for(let n of e)i.start(`Stopping and removing ${n}...`),await r.stop([n]),await r.remove([n]),await Es(As(t.directory,n),{force:!0,recursive:!0}),i.stop(`${m.red("-")} ${n}`)}}class le extends I{name="profile";description="Manage profiles";init(){this.registerSubcommands([new Je,new Xe,new Ye])}}import{rm as Ds}from"fs/promises";import{join as ks}from"path";var Ls=M({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class ce extends I{name="remove";description="Deregister and remove runners";positionals=Ls;async execute(t){let{name:e,profile:r}=t.interactive?V(t.config,await K(t.config)):V(t.config,t.positionals.profile),i=t.config.get("runners")??[],n=i.filter((l)=>l.profile===e);if(n.length===0)throw new v(`No runners found for profile "${e}"`,"Run hydra create to provision runners");let s=t.interactive?await this.promptRunnerSelection(n.map((l)=>l.id)):gt(t.positionals.ids??[],n.map((l)=>l.id)),o=O(r),a=B();for(let l of s)a.start(`Stopping and removing ${l}...`),await o.stop([l]),await o.remove([l]),await Ds(ks(r.directory,l),{force:!0,recursive:!0}),a.stop(`${m.red("-")} ${l}`);let u=i.filter((l)=>!s.includes(l.id));t.config.set("runners",u),$.info(`${m.green("Removed")} ${s.length} runner(s).`)}async promptRunnerSelection(t){return lt({message:"Select runners to remove",options:t.map((e)=>({label:e,value:e})),required:!0})}}var Fs=M({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class pe extends I{name="start";description="Start runners";positionals=Fs;async execute(t){let{name:e,profile:r}=t.interactive?V(t.config,await K(t.config)):V(t.config,t.positionals.profile),n=(t.config.get("runners")??[]).filter((p)=>p.profile===e);if(n.length===0)throw new v(`No runners found for profile "${e}"`,"Run hydra create to provision runners");let s=O(r),o=B();o.start("Fetching runner status...");let a=await s.list();o.stop("Runner status fetched");let u=new Set(a.filter((p)=>p.status==="running").map((p)=>p.id)),l=n.map((p)=>p.id).filter((p)=>!u.has(p)),h=t.interactive?await this.promptRunnerSelection(l):gt(t.positionals.ids??[],n.map((p)=>p.id)),f=0;for(let p of h){if(u.has(p)){o.start(""),o.stop(`${m.dim("\u25CF")} ${p} ${m.dim("already running")}`);continue}o.start(`Starting ${p}...`),await s.start([p]),o.stop(`${m.green("\u25B6")} ${p}`),f++}$.info(`${m.green("Started")} ${f} runner(s).`),await Et(t)}async promptRunnerSelection(t){if(t.length===0)throw new v("All runners are already running");return lt({message:"Select runners to start",options:t.map((e)=>({label:e,value:e})),required:!0})}}var Ns={registered:m.yellow,running:m.green,stopped:m.red,unknown:m.dim};class me extends I{name="status";description="Show runner status across all profiles";async execute(t){let e=t.config.get("profiles"),r=Object.keys(e);if(r.length===0)throw new v("No profiles configured","Run hydra init to set up a profile");let i=t.config.get("runners")??[],n=0,s=0,o=[];for(let a of r){let u=e[a],h=await O(u).list();if(o.length>0)o.push("");o.push(`${m.bold(a)} ${m.dim(u.url)}`);let f=new Set(i.filter((g)=>g.profile===a).map((g)=>g.id)),p=h.filter((g)=>f.has(g.id)).sort((g,d)=>g.name.localeCompare(d.name,void 0,{numeric:!0}));this.formatRunners(p,o),n+=p.length,s+=p.filter((g)=>g.status==="running").length}o.push(""),o.push(m.dim(`${n} runner(s) total, ${s} running`)),$.info(o.join(`
|
|
99
|
+
`))}formatRunners(t,e){if(t.length===0){e.push(m.dim(" No runners."));return}for(let r of t){let i=Ns[r.status]??m.dim,n=r.pid?m.dim(` (pid: ${r.pid})`):"";e.push(` ${i("\u25CF")} ${r.name} ${i(r.status)}${n}`)}}}var Ms=M({profile:{description:"Profile name"},ids:{description:"Runner IDs (omit to target all)",variadic:!0}});class de extends I{name="stop";description="Stop runners";positionals=Ms;async execute(t){let{name:e,profile:r}=t.interactive?V(t.config,await K(t.config)):V(t.config,t.positionals.profile),n=(t.config.get("runners")??[]).filter((p)=>p.profile===e);if(n.length===0)throw new v(`No runners found for profile "${e}"`,"Run hydra create to provision runners");let s=O(r),o=B();o.start("Fetching runner status...");let a=await s.list();o.stop("Runner status fetched");let u=new Set(a.filter((p)=>p.status==="running").map((p)=>p.id)),l=n.map((p)=>p.id).filter((p)=>u.has(p)),h=t.interactive?await this.promptRunnerSelection(l):gt(t.positionals.ids??[],n.map((p)=>p.id)),f=0;for(let p of h){if(!u.has(p)){o.start(""),o.stop(`${m.dim("\u25CF")} ${p} ${m.dim("not running")}`);continue}o.start(`Stopping ${p}...`),await s.stop([p]),o.stop(`${m.red("\u25A0")} ${p}`),f++}$.info(`${m.green("Stopped")} ${f} runner(s).`)}async promptRunnerSelection(t){if(t.length===0)throw new v("No runners are currently running");return lt({message:"Select runners to stop",options:t.map((e)=>({label:e,value:e})),required:!0})}}class he extends I{name="update";description="Update runners to the latest version";async execute(t){let e=t.config.get("profiles"),r=t.config.get("runners")??[];if(r.length===0)throw new v("No runners found","Run hydra create to provision runners");let i=B(),n=Map.groupBy(r,(u)=>u.profile),s=null,o="",a=!1;for(let[u,l]of n){let h=e[u],f=l[0];if(!h||!f)continue;let p=O(h);if(!a){if(a=!0,i.start("Checking for updates..."),o=(await p.download()).version,s=await p.currentVersion(f.id),i.stop(`Current: v${s??"unknown"} | Latest: v${o}`),s===o){$.info(`Already on latest version ${m.dim(`(v${o})`)}`),await Et(t);return}}let g=await p.list(),d=new Set(g.filter((y)=>y.status==="running").map((y)=>y.id));for(let y of l){let R=d.has(y.id);if(i.start(`Updating ${y.id}...`),R)await p.stop([y.id]);if(await p.update([y.id]),R)await p.start([y.id]);let E=R?` ${m.dim("(restarted)")}`:"";i.stop(`${m.green("\u2713")} ${y.id}${E}`)}}$.info(`${m.green("Updated")} ${r.length} runner(s) from v${s} to v${o}`),await Et(t)}}class wi extends Me{constructor(){super(new Oe(zr,Yr),{bin:Jt,clearOnStart:!0,exitLabel:"Exit",goodbyeMessage:"Heads down.",name:"HYDRA",promptMessage:"What do you need?",version:qr})}init(){this.registerCommands([new ae,new oe,new pe,new de,new me,new ue,new se,new ce,new he,new le])}}var Os=new wi;Os.run();
|
package/package.json
CHANGED
|
@@ -4,13 +4,6 @@
|
|
|
4
4
|
"hydra": "dist/cli.js"
|
|
5
5
|
},
|
|
6
6
|
"description": "A tool for spawning multiple local GitHub self-hosted runners",
|
|
7
|
-
"dependencies": {
|
|
8
|
-
"@r5n/cli-core": "workspace:*"
|
|
9
|
-
},
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"@clack/prompts": "1.7.0",
|
|
12
|
-
"@r5n/tools": "workspace:*"
|
|
13
|
-
},
|
|
14
7
|
"files": [
|
|
15
8
|
"dist",
|
|
16
9
|
"schema.json",
|
|
@@ -43,5 +36,5 @@
|
|
|
43
36
|
},
|
|
44
37
|
"type": "module",
|
|
45
38
|
"types": "src/cli.ts",
|
|
46
|
-
"version": "0.
|
|
39
|
+
"version": "0.8.0"
|
|
47
40
|
}
|
package/schema.json
CHANGED
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Add this to your hydra.json: \"$schema\": \"https://raw.githubusercontent.com/r5n-labs/clis/refs/heads/develop/packages/hydra/schema.json\"",
|
|
2
|
+
"$comment": "Add this to your .hydra/config.json: \"$schema\": \"https://raw.githubusercontent.com/r5n-labs/clis/refs/heads/develop/packages/hydra/schema.json\"",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"additionalProperties": false,
|
|
5
5
|
"definitions": {
|
|
6
|
+
"cleanup": {
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"auto": {
|
|
10
|
+
"default": false,
|
|
11
|
+
"description": "Run cleanup automatically after hydra start and hydra update",
|
|
12
|
+
"type": "boolean"
|
|
13
|
+
},
|
|
14
|
+
"intervalHours": {
|
|
15
|
+
"default": 24,
|
|
16
|
+
"description": "Minimum hours between automatic cleanup runs",
|
|
17
|
+
"minimum": 1,
|
|
18
|
+
"type": "integer"
|
|
19
|
+
},
|
|
20
|
+
"lastRun": {
|
|
21
|
+
"description": "ISO timestamp of the last cleanup run; managed by Hydra, do not edit by hand",
|
|
22
|
+
"format": "date-time",
|
|
23
|
+
"type": "string"
|
|
24
|
+
},
|
|
25
|
+
"olderThanDays": {
|
|
26
|
+
"default": 7,
|
|
27
|
+
"description": "Prune log files older than this many days",
|
|
28
|
+
"minimum": 0,
|
|
29
|
+
"type": "integer"
|
|
30
|
+
},
|
|
31
|
+
"targets": {
|
|
32
|
+
"default": ["logs", "shared"],
|
|
33
|
+
"description": "What to clean: _diag log files, _work job workspaces, unused shared runner versions",
|
|
34
|
+
"items": { "enum": ["logs", "work", "shared"], "type": "string" },
|
|
35
|
+
"type": "array"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"type": "object"
|
|
39
|
+
},
|
|
6
40
|
"profile": {
|
|
7
41
|
"additionalProperties": false,
|
|
8
42
|
"properties": {
|
|
9
43
|
"directory": {
|
|
10
|
-
"default": "
|
|
44
|
+
"default": ".hydra/runners",
|
|
11
45
|
"description": "Directory where runners will be created",
|
|
12
46
|
"type": "string"
|
|
13
47
|
},
|
|
@@ -26,25 +60,65 @@
|
|
|
26
60
|
"type": "string"
|
|
27
61
|
},
|
|
28
62
|
"overwrite": { "default": false, "description": "Whether to overwrite existing runners", "type": "boolean" },
|
|
63
|
+
"provider": {
|
|
64
|
+
"default": "github",
|
|
65
|
+
"description": "Runner provider backing this profile",
|
|
66
|
+
"enum": ["github", "gitlab"],
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
29
69
|
"run": {
|
|
30
70
|
"default": false,
|
|
31
71
|
"description": "Whether to start runners immediately after creation",
|
|
32
72
|
"type": "boolean"
|
|
33
73
|
},
|
|
34
|
-
"runnerGroup": {
|
|
35
|
-
|
|
74
|
+
"runnerGroup": {
|
|
75
|
+
"description": "Runner group to assign runners to (applies to organization runners)",
|
|
76
|
+
"type": "string"
|
|
77
|
+
},
|
|
78
|
+
"url": {
|
|
79
|
+
"description": "GitHub repository URL (https://github.com/<owner>/<repo>) or organization URL (https://github.com/<org>)",
|
|
80
|
+
"format": "uri",
|
|
81
|
+
"type": "string"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"type": "object"
|
|
85
|
+
},
|
|
86
|
+
"runnerEntry": {
|
|
87
|
+
"additionalProperties": false,
|
|
88
|
+
"properties": {
|
|
89
|
+
"createdAt": { "description": "ISO timestamp of when the runner was created", "type": "string" },
|
|
90
|
+
"directory": { "description": "Directory of the runner installation", "type": "string" },
|
|
91
|
+
"id": { "description": "Runner identifier", "type": "string" },
|
|
92
|
+
"name": { "description": "Runner name as registered with the provider", "type": "string" },
|
|
93
|
+
"profile": { "description": "Profile the runner belongs to", "type": "string" },
|
|
94
|
+
"provider": {
|
|
95
|
+
"description": "Provider the runner is registered with",
|
|
96
|
+
"enum": ["github", "gitlab"],
|
|
97
|
+
"type": "string"
|
|
98
|
+
},
|
|
99
|
+
"url": { "description": "Repository or organization URL the runner is registered against", "type": "string" }
|
|
36
100
|
},
|
|
101
|
+
"required": ["id", "name", "profile", "provider", "url", "directory", "createdAt"],
|
|
37
102
|
"type": "object"
|
|
38
103
|
}
|
|
39
104
|
},
|
|
40
105
|
"description": "Configuration for Hydra GitHub self-hosted runner manager",
|
|
41
106
|
"properties": {
|
|
42
107
|
"$schema": { "description": "JSON Schema reference for IDE support", "type": "string" },
|
|
108
|
+
"cleanup": {
|
|
109
|
+
"$ref": "#/definitions/cleanup",
|
|
110
|
+
"description": "Disk cleanup behavior for hydra cleanup and automatic cleanup"
|
|
111
|
+
},
|
|
43
112
|
"defaultProfile": { "description": "The default profile to use when no profile is specified", "type": "string" },
|
|
44
113
|
"profiles": {
|
|
45
114
|
"additionalProperties": { "$ref": "#/definitions/profile" },
|
|
46
115
|
"description": "Named profiles for different runner configurations",
|
|
47
116
|
"type": "object"
|
|
117
|
+
},
|
|
118
|
+
"runners": {
|
|
119
|
+
"description": "Runners Hydra has created; managed by Hydra, do not edit by hand",
|
|
120
|
+
"items": { "$ref": "#/definitions/runnerEntry" },
|
|
121
|
+
"type": "array"
|
|
48
122
|
}
|
|
49
123
|
},
|
|
50
124
|
"required": ["profiles"],
|