byollm 0.1.0-alpha.39 → 0.1.0-alpha.40
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 +48 -2
- package/dist/bin.js +1 -1
- package/dist/{chunk-GBQBJAT7.js → chunk-RYUKSHXG.js} +342 -14
- package/dist/{chunk-GBQBJAT7.js.map → chunk-RYUKSHXG.js.map} +1 -1
- package/dist/index.d.ts +79 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
> [!WARNING]
|
|
2
|
-
> **Alpha (`0.1.0-alpha.
|
|
2
|
+
> **Alpha (`0.1.0-alpha.40`) — under active development. Don't use this yet.**
|
|
3
3
|
>
|
|
4
4
|
> Install it deliberately: `npx byollm@alpha`, or `npm install byollm@alpha`.
|
|
5
5
|
>
|
|
@@ -85,12 +85,25 @@
|
|
|
85
85
|
> packages published and `@byollm/server` did not: a Sigstore
|
|
86
86
|
> transparency-log 409 on its provenance attestation. The workflow's
|
|
87
87
|
> "already published" guard correctly refuses to resume a partial publish,
|
|
88
|
-
> so `0.1.0-alpha.
|
|
88
|
+
> so `0.1.0-alpha.40` is that release, whole.
|
|
89
89
|
>
|
|
90
90
|
> If you run the Supabase adapter, `alpha.21` needs
|
|
91
91
|
> `20260819010000_completed_by_lease_id.sql`: alpha.19 shipped §3.6's
|
|
92
92
|
> ordering without the column it stores the grant in.
|
|
93
93
|
|
|
94
|
+
<!-- release-note 0.1.0-alpha.40 -->
|
|
95
|
+
**`byollm install` — stop keeping a terminal open.** The daemon can now run
|
|
96
|
+
under your machine's own supervisor and restart itself if it stops: a launchd
|
|
97
|
+
agent on macOS, a `systemd --user` unit on Linux, a logon task on Windows. All
|
|
98
|
+
user-level — no root, no system directories, and `byollm uninstall` takes it
|
|
99
|
+
away. `byollm status` gained a line saying whether it is actually supervised
|
|
100
|
+
right now, including the state that matters most: installed but not running,
|
|
101
|
+
which looks fine from an app's dashboard and serves nothing.
|
|
102
|
+
|
|
103
|
+
If you are running via `npx`, install properly first (`npm install -g
|
|
104
|
+
byollm@alpha`) — `install` refuses to supervise a copy in npx's cache, because
|
|
105
|
+
npm deletes that directory and the service would fail at some later boot.
|
|
106
|
+
|
|
94
107
|
# `byollm`
|
|
95
108
|
|
|
96
109
|
What end users run. Connects **outbound** to an app you trust, claims only the
|
|
@@ -158,6 +171,39 @@ URL, a path or a flag — there is no field on the wire for any of them.
|
|
|
158
171
|
therefore advertised. A backend that is down is never advertised, so you never
|
|
159
172
|
get work you cannot run.
|
|
160
173
|
|
|
174
|
+
## Keep it running
|
|
175
|
+
|
|
176
|
+
By default `byollm connect` and `byollm run` hold a terminal — close the
|
|
177
|
+
window and the machine stops serving. Nothing breaks (your pairings live in
|
|
178
|
+
`~/.byollm/pairings.json` and survive), but the machine goes quiet without
|
|
179
|
+
telling anyone, and if it is on a team's roster, the first person to notice is
|
|
180
|
+
a teammate whose job did not run.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
byollm install # keep running in the background, and restart if it stops
|
|
184
|
+
byollm status # says whether it is actually supervised right now
|
|
185
|
+
byollm uninstall
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
It installs at the user level on every platform — a launchd `LaunchAgent` on
|
|
189
|
+
macOS, a `systemd --user` unit on Linux, a logon task on Windows. No root, no
|
|
190
|
+
system directories: it runs as you, it stops when you say so, and you can read
|
|
191
|
+
every file it wrote. Output goes to `~/.byollm/service.log` on all three.
|
|
192
|
+
|
|
193
|
+
Two things worth knowing:
|
|
194
|
+
|
|
195
|
+
- **Install `byollm` properly first.** `byollm install` refuses to supervise a
|
|
196
|
+
copy running from `npx`'s cache, because npm deletes that directory without
|
|
197
|
+
warning and the service would stop working at some later boot with nothing
|
|
198
|
+
to show for it. `npm install -g byollm@alpha` first.
|
|
199
|
+
- **On Linux, `systemd --user` stops when you log out** unless lingering is
|
|
200
|
+
enabled. `byollm install` prints the one command for that rather than
|
|
201
|
+
running it — it changes something outside your session, so it is your call.
|
|
202
|
+
|
|
203
|
+
`byollm status` reports three states, not two: running under supervision,
|
|
204
|
+
*installed but not running* (the one that looks fine from an app's dashboard
|
|
205
|
+
and serves nothing), and not installed at all.
|
|
206
|
+
|
|
161
207
|
## The trust surface
|
|
162
208
|
|
|
163
209
|
The meter is the product, and it gets the same care as the loop.
|
package/dist/bin.js
CHANGED
|
@@ -96,9 +96,9 @@ function normalizeOrigin(input) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// src/cli.ts
|
|
99
|
-
import { mkdir as
|
|
99
|
+
import { mkdir as mkdir8, readFile as readFile8, rm as rm5, stat as stat2, writeFile as writeFile8 } from "fs/promises";
|
|
100
100
|
import { hostname, userInfo } from "os";
|
|
101
|
-
import { dirname as
|
|
101
|
+
import { dirname as dirname8 } from "path";
|
|
102
102
|
import { createInterface } from "readline/promises";
|
|
103
103
|
import { backendDescriptor as backendDescriptor3, resolveCost as resolveCost2 } from "@byollm/protocol";
|
|
104
104
|
|
|
@@ -3023,6 +3023,273 @@ function sleep(ms, signal) {
|
|
|
3023
3023
|
});
|
|
3024
3024
|
}
|
|
3025
3025
|
|
|
3026
|
+
// src/install.ts
|
|
3027
|
+
import { mkdir as mkdir7, rm as rm4, writeFile as writeFile7 } from "fs/promises";
|
|
3028
|
+
import { dirname as dirname7 } from "path";
|
|
3029
|
+
|
|
3030
|
+
// src/service.ts
|
|
3031
|
+
import { homedir as homedir2 } from "os";
|
|
3032
|
+
import { join as join3 } from "path";
|
|
3033
|
+
var SERVICE_LABEL = "cloud.byollm.daemon";
|
|
3034
|
+
function xml(value) {
|
|
3035
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3036
|
+
}
|
|
3037
|
+
function servicePlan(target) {
|
|
3038
|
+
const home = target.home ?? homedir2();
|
|
3039
|
+
const root = target.root ?? join3(home, ".byollm");
|
|
3040
|
+
const logPath = join3(root, "service.log");
|
|
3041
|
+
const { execPath, scriptPath } = target;
|
|
3042
|
+
if (target.platform === "darwin") {
|
|
3043
|
+
const unitPath2 = join3(
|
|
3044
|
+
home,
|
|
3045
|
+
"Library",
|
|
3046
|
+
"LaunchAgents",
|
|
3047
|
+
`${SERVICE_LABEL}.plist`
|
|
3048
|
+
);
|
|
3049
|
+
const unitContents2 = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3050
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3051
|
+
<plist version="1.0">
|
|
3052
|
+
<dict>
|
|
3053
|
+
<key>Label</key><string>${SERVICE_LABEL}</string>
|
|
3054
|
+
<key>ProgramArguments</key>
|
|
3055
|
+
<array>
|
|
3056
|
+
<string>${xml(execPath)}</string>
|
|
3057
|
+
<string>${xml(scriptPath)}</string>
|
|
3058
|
+
<string>run</string>
|
|
3059
|
+
</array>
|
|
3060
|
+
<key>RunAtLoad</key><true/>
|
|
3061
|
+
<key>KeepAlive</key><true/>
|
|
3062
|
+
<key>ThrottleInterval</key><integer>10</integer>
|
|
3063
|
+
<key>StandardOutPath</key><string>${xml(logPath)}</string>
|
|
3064
|
+
<key>StandardErrorPath</key><string>${xml(logPath)}</string>
|
|
3065
|
+
<key>ProcessType</key><string>Background</string>
|
|
3066
|
+
</dict>
|
|
3067
|
+
</plist>
|
|
3068
|
+
`;
|
|
3069
|
+
const domain = `gui/${String(target.uid ?? 0)}`;
|
|
3070
|
+
return {
|
|
3071
|
+
platform: "darwin",
|
|
3072
|
+
unitPath: unitPath2,
|
|
3073
|
+
unitContents: unitContents2,
|
|
3074
|
+
activate: [
|
|
3075
|
+
["launchctl", "bootout", domain, unitPath2],
|
|
3076
|
+
["launchctl", "bootstrap", domain, unitPath2],
|
|
3077
|
+
["launchctl", "enable", `${domain}/${SERVICE_LABEL}`]
|
|
3078
|
+
],
|
|
3079
|
+
deactivate: [["launchctl", "bootout", domain, unitPath2]],
|
|
3080
|
+
query: ["launchctl", "print", `${domain}/${SERVICE_LABEL}`],
|
|
3081
|
+
logPath,
|
|
3082
|
+
supervisor: "launchd"
|
|
3083
|
+
};
|
|
3084
|
+
}
|
|
3085
|
+
if (target.platform === "linux") {
|
|
3086
|
+
const unitPath2 = join3(
|
|
3087
|
+
home,
|
|
3088
|
+
".config",
|
|
3089
|
+
"systemd",
|
|
3090
|
+
"user",
|
|
3091
|
+
`${SERVICE_LABEL}.service`
|
|
3092
|
+
);
|
|
3093
|
+
const unitContents2 = `[Unit]
|
|
3094
|
+
Description=byollm \u2014 run an app's LLM jobs on your own models
|
|
3095
|
+
Documentation=https://byo-llm.com/docs
|
|
3096
|
+
After=network-online.target
|
|
3097
|
+
|
|
3098
|
+
[Service]
|
|
3099
|
+
Type=simple
|
|
3100
|
+
ExecStart=${execPath} ${scriptPath} run
|
|
3101
|
+
Restart=always
|
|
3102
|
+
RestartSec=10
|
|
3103
|
+
# Output goes to the journal *and* to the same file the other platforms use,
|
|
3104
|
+
# so "where are the logs" has one answer in the docs.
|
|
3105
|
+
StandardOutput=append:${logPath}
|
|
3106
|
+
StandardError=append:${logPath}
|
|
3107
|
+
|
|
3108
|
+
[Install]
|
|
3109
|
+
WantedBy=default.target
|
|
3110
|
+
`;
|
|
3111
|
+
return {
|
|
3112
|
+
platform: "linux",
|
|
3113
|
+
unitPath: unitPath2,
|
|
3114
|
+
unitContents: unitContents2,
|
|
3115
|
+
activate: [
|
|
3116
|
+
["systemctl", "--user", "daemon-reload"],
|
|
3117
|
+
["systemctl", "--user", "enable", "--now", `${SERVICE_LABEL}.service`]
|
|
3118
|
+
],
|
|
3119
|
+
deactivate: [
|
|
3120
|
+
["systemctl", "--user", "disable", "--now", `${SERVICE_LABEL}.service`],
|
|
3121
|
+
["systemctl", "--user", "daemon-reload"]
|
|
3122
|
+
],
|
|
3123
|
+
query: ["systemctl", "--user", "is-active", `${SERVICE_LABEL}.service`],
|
|
3124
|
+
logPath,
|
|
3125
|
+
supervisor: "systemd (user)"
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
const unitPath = join3(root, "byollm-task.xml");
|
|
3129
|
+
const unitContents = `<?xml version="1.0" encoding="UTF-16"?>
|
|
3130
|
+
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
3131
|
+
<RegistrationInfo>
|
|
3132
|
+
<Description>byollm \u2014 run an app's LLM jobs on your own models</Description>
|
|
3133
|
+
</RegistrationInfo>
|
|
3134
|
+
<Triggers>
|
|
3135
|
+
<LogonTrigger><Enabled>true</Enabled></LogonTrigger>
|
|
3136
|
+
</Triggers>
|
|
3137
|
+
<Settings>
|
|
3138
|
+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
3139
|
+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
3140
|
+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
3141
|
+
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
3142
|
+
<RestartOnFailure>
|
|
3143
|
+
<Interval>PT1M</Interval>
|
|
3144
|
+
<Count>999</Count>
|
|
3145
|
+
</RestartOnFailure>
|
|
3146
|
+
</Settings>
|
|
3147
|
+
<Actions>
|
|
3148
|
+
<Exec>
|
|
3149
|
+
<Command>${xml(execPath)}</Command>
|
|
3150
|
+
<Arguments>"${xml(scriptPath)}" run</Arguments>
|
|
3151
|
+
</Exec>
|
|
3152
|
+
</Actions>
|
|
3153
|
+
</Task>
|
|
3154
|
+
`;
|
|
3155
|
+
return {
|
|
3156
|
+
platform: "win32",
|
|
3157
|
+
unitPath,
|
|
3158
|
+
unitContents,
|
|
3159
|
+
activate: [
|
|
3160
|
+
["schtasks", "/create", "/tn", SERVICE_LABEL, "/xml", unitPath, "/f"],
|
|
3161
|
+
["schtasks", "/run", "/tn", SERVICE_LABEL]
|
|
3162
|
+
],
|
|
3163
|
+
deactivate: [["schtasks", "/delete", "/tn", SERVICE_LABEL, "/f"]],
|
|
3164
|
+
query: ["schtasks", "/query", "/tn", SERVICE_LABEL],
|
|
3165
|
+
logPath,
|
|
3166
|
+
supervisor: "Task Scheduler"
|
|
3167
|
+
};
|
|
3168
|
+
}
|
|
3169
|
+
function refuseToSupervise(scriptPath) {
|
|
3170
|
+
const ephemeral = /[/\\]_npx[/\\]|[/\\]\.npm[/\\]_cacache[/\\]|[/\\]npm-cache[/\\]_npx[/\\]/;
|
|
3171
|
+
if (ephemeral.test(scriptPath)) {
|
|
3172
|
+
return `this copy of byollm lives in npx's cache (${scriptPath}), which npm deletes without warning \u2014 a service pointing at it would stop working at some later boot, silently.
|
|
3173
|
+
|
|
3174
|
+
Install it properly first: npm install -g byollm@alpha
|
|
3175
|
+
Then: byollm install`;
|
|
3176
|
+
}
|
|
3177
|
+
return null;
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
// src/install.ts
|
|
3181
|
+
async function serviceState(plan, run2) {
|
|
3182
|
+
const result = await run2(plan.query).catch(() => ({
|
|
3183
|
+
code: 127,
|
|
3184
|
+
output: ""
|
|
3185
|
+
}));
|
|
3186
|
+
if (result.code !== 0) return { state: "absent" };
|
|
3187
|
+
if (plan.platform === "darwin") {
|
|
3188
|
+
if (/\bstate = running\b/.test(result.output) || /\n\s*pid = \d+/.test(result.output)) {
|
|
3189
|
+
return { state: "running" };
|
|
3190
|
+
}
|
|
3191
|
+
const last = /last exit (?:code|status) = (-?\d+)/.exec(result.output);
|
|
3192
|
+
return {
|
|
3193
|
+
state: "installed",
|
|
3194
|
+
detail: last === null ? "loaded but not running" : `not running (last exit ${last[1] ?? "?"})`
|
|
3195
|
+
};
|
|
3196
|
+
}
|
|
3197
|
+
if (plan.platform === "linux") {
|
|
3198
|
+
const word = result.output.trim();
|
|
3199
|
+
return word === "active" ? { state: "running" } : { state: "installed", detail: word === "" ? "not running" : word };
|
|
3200
|
+
}
|
|
3201
|
+
if (/\bRunning\b/.test(result.output)) return { state: "running" };
|
|
3202
|
+
return { state: "installed", detail: "registered, not running" };
|
|
3203
|
+
}
|
|
3204
|
+
async function installService(target, run2) {
|
|
3205
|
+
const plan = servicePlan(target);
|
|
3206
|
+
const refusal = refuseToSupervise(target.scriptPath);
|
|
3207
|
+
if (refusal !== null) {
|
|
3208
|
+
return { ok: false, lines: [refusal], plan };
|
|
3209
|
+
}
|
|
3210
|
+
await mkdir7(dirname7(plan.unitPath), { recursive: true });
|
|
3211
|
+
await writeFile7(plan.unitPath, plan.unitContents, "utf8");
|
|
3212
|
+
for (const [index, command] of plan.activate.entries()) {
|
|
3213
|
+
const result = await run2(command);
|
|
3214
|
+
const mayFail = plan.platform === "darwin" && index === 0;
|
|
3215
|
+
if (result.code !== 0 && !mayFail) {
|
|
3216
|
+
return {
|
|
3217
|
+
ok: false,
|
|
3218
|
+
plan,
|
|
3219
|
+
lines: [
|
|
3220
|
+
`wrote ${plan.unitPath}, but ${plan.supervisor} refused it:`,
|
|
3221
|
+
"",
|
|
3222
|
+
` ${command.join(" ")}`,
|
|
3223
|
+
` exit ${String(result.code)}${result.output.trim() === "" ? "" : `: ${result.output.trim()}`}`,
|
|
3224
|
+
"",
|
|
3225
|
+
`The daemon is not supervised. \`byollm run\` still works in a terminal.`
|
|
3226
|
+
]
|
|
3227
|
+
};
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
const lines = [
|
|
3231
|
+
`Installed. ${plan.supervisor} will keep byollm running and restart it if it stops.`,
|
|
3232
|
+
"",
|
|
3233
|
+
` service: ${plan.unitPath}`,
|
|
3234
|
+
` log: ${plan.logPath}`,
|
|
3235
|
+
` check: byollm status`,
|
|
3236
|
+
` remove: byollm uninstall`
|
|
3237
|
+
];
|
|
3238
|
+
if (plan.platform === "linux") {
|
|
3239
|
+
lines.push(
|
|
3240
|
+
"",
|
|
3241
|
+
"To keep serving after you log out:",
|
|
3242
|
+
"",
|
|
3243
|
+
" sudo loginctl enable-linger $USER"
|
|
3244
|
+
);
|
|
3245
|
+
}
|
|
3246
|
+
return { ok: true, plan, lines };
|
|
3247
|
+
}
|
|
3248
|
+
async function uninstallService(target, run2) {
|
|
3249
|
+
const plan = servicePlan(target);
|
|
3250
|
+
const failures = [];
|
|
3251
|
+
for (const command of plan.deactivate) {
|
|
3252
|
+
const result = await run2(command).catch(() => ({ code: 127, output: "" }));
|
|
3253
|
+
if (result.code !== 0 && result.output.trim() !== "") {
|
|
3254
|
+
failures.push(` ${command.join(" ")} \u2014 ${result.output.trim()}`);
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
await rm4(plan.unitPath, { force: true });
|
|
3258
|
+
return {
|
|
3259
|
+
ok: true,
|
|
3260
|
+
plan,
|
|
3261
|
+
lines: [
|
|
3262
|
+
`Removed. ${plan.supervisor} is no longer running byollm.`,
|
|
3263
|
+
`Your pairings, allowlist and logs are untouched in ~/.byollm.`,
|
|
3264
|
+
...failures.length === 0 ? [] : [
|
|
3265
|
+
"",
|
|
3266
|
+
"The supervisor had something to say (usually harmless):",
|
|
3267
|
+
...failures
|
|
3268
|
+
]
|
|
3269
|
+
]
|
|
3270
|
+
};
|
|
3271
|
+
}
|
|
3272
|
+
var spawnCommand = async (command) => {
|
|
3273
|
+
const { spawn: spawn2 } = await import("child_process");
|
|
3274
|
+
const [file, ...args] = command;
|
|
3275
|
+
return new Promise((resolve) => {
|
|
3276
|
+
const child = spawn2(file ?? "", args);
|
|
3277
|
+
let output = "";
|
|
3278
|
+
child.stdout.on("data", (chunk) => {
|
|
3279
|
+
output += chunk.toString();
|
|
3280
|
+
});
|
|
3281
|
+
child.stderr.on("data", (chunk) => {
|
|
3282
|
+
output += chunk.toString();
|
|
3283
|
+
});
|
|
3284
|
+
child.on("error", () => {
|
|
3285
|
+
resolve({ code: 127, output });
|
|
3286
|
+
});
|
|
3287
|
+
child.on("close", (code) => {
|
|
3288
|
+
resolve({ code: code ?? 0, output });
|
|
3289
|
+
});
|
|
3290
|
+
});
|
|
3291
|
+
};
|
|
3292
|
+
|
|
3026
3293
|
// src/cli.ts
|
|
3027
3294
|
var USAGE = `byollm \u2014 run an app's LLM jobs on your own models.
|
|
3028
3295
|
|
|
@@ -3041,6 +3308,8 @@ var USAGE = `byollm \u2014 run an app's LLM jobs on your own models.
|
|
|
3041
3308
|
byollm approve <site> serve a site that asked (or --all)
|
|
3042
3309
|
byollm forget <url> drop a pairing
|
|
3043
3310
|
byollm backends what is installed, healthy, and advertised
|
|
3311
|
+
byollm install keep running in the background, across restarts
|
|
3312
|
+
byollm uninstall stop running in the background
|
|
3044
3313
|
|
|
3045
3314
|
Config lives in ~/.byollm/config.json. Everything this daemon has ever run is
|
|
3046
3315
|
in ~/.byollm/ingress.log \u2014 it is yours to read and yours to delete.
|
|
@@ -3055,6 +3324,7 @@ async function runCli(argv, options = {}) {
|
|
|
3055
3324
|
const paths = options.paths ?? daemonPaths();
|
|
3056
3325
|
const io = { ...defaultIo, ...options.io };
|
|
3057
3326
|
const signal = options.signal;
|
|
3327
|
+
const service = options.service ?? defaultServiceIo();
|
|
3058
3328
|
switch (command) {
|
|
3059
3329
|
case void 0:
|
|
3060
3330
|
case "help":
|
|
@@ -3073,7 +3343,7 @@ async function runCli(argv, options = {}) {
|
|
|
3073
3343
|
case "run":
|
|
3074
3344
|
return commandRun(paths, rest, io, signal);
|
|
3075
3345
|
case "status":
|
|
3076
|
-
return commandStatus(paths, io);
|
|
3346
|
+
return commandStatus(paths, io, service);
|
|
3077
3347
|
case "log":
|
|
3078
3348
|
return commandLog(paths, rest, io);
|
|
3079
3349
|
case "pause":
|
|
@@ -3094,6 +3364,10 @@ async function runCli(argv, options = {}) {
|
|
|
3094
3364
|
return commandForget(paths, rest, io);
|
|
3095
3365
|
case "backends":
|
|
3096
3366
|
return commandBackends(paths, io);
|
|
3367
|
+
case "install":
|
|
3368
|
+
return commandInstall(paths, io, service);
|
|
3369
|
+
case "uninstall":
|
|
3370
|
+
return commandUninstall(paths, io, service);
|
|
3097
3371
|
default:
|
|
3098
3372
|
io.err(`unknown command: ${command}
|
|
3099
3373
|
|
|
@@ -3101,6 +3375,59 @@ ${USAGE}`);
|
|
|
3101
3375
|
return 2;
|
|
3102
3376
|
}
|
|
3103
3377
|
}
|
|
3378
|
+
function defaultServiceIo() {
|
|
3379
|
+
return {
|
|
3380
|
+
platform: process.platform === "win32" ? "win32" : process.platform === "darwin" ? "darwin" : "linux",
|
|
3381
|
+
execPath: process.execPath,
|
|
3382
|
+
scriptPath: process.argv[1] ?? "",
|
|
3383
|
+
run: spawnCommand,
|
|
3384
|
+
// `getuid` is absent on Windows, where nothing reads it.
|
|
3385
|
+
uid: process.getuid?.() ?? 0
|
|
3386
|
+
};
|
|
3387
|
+
}
|
|
3388
|
+
function serviceTarget(paths, service) {
|
|
3389
|
+
return {
|
|
3390
|
+
platform: service.platform,
|
|
3391
|
+
execPath: service.execPath,
|
|
3392
|
+
scriptPath: service.scriptPath,
|
|
3393
|
+
...service.home === void 0 ? {} : { home: service.home },
|
|
3394
|
+
...service.uid === void 0 ? {} : { uid: service.uid },
|
|
3395
|
+
root: paths.root
|
|
3396
|
+
};
|
|
3397
|
+
}
|
|
3398
|
+
async function commandInstall(paths, io, service) {
|
|
3399
|
+
const result = await installService(
|
|
3400
|
+
serviceTarget(paths, service),
|
|
3401
|
+
service.run
|
|
3402
|
+
);
|
|
3403
|
+
for (const line of result.lines) (result.ok ? io.out : io.err)(`${line}
|
|
3404
|
+
`);
|
|
3405
|
+
return result.ok ? 0 : 1;
|
|
3406
|
+
}
|
|
3407
|
+
async function commandUninstall(paths, io, service) {
|
|
3408
|
+
const result = await uninstallService(
|
|
3409
|
+
serviceTarget(paths, service),
|
|
3410
|
+
service.run
|
|
3411
|
+
);
|
|
3412
|
+
for (const line of result.lines) io.out(`${line}
|
|
3413
|
+
`);
|
|
3414
|
+
return 0;
|
|
3415
|
+
}
|
|
3416
|
+
async function supervisionLine(paths, service) {
|
|
3417
|
+
const plan = servicePlan(serviceTarget(paths, service));
|
|
3418
|
+
const state = await serviceState(plan, service.run);
|
|
3419
|
+
switch (state.state) {
|
|
3420
|
+
case "running":
|
|
3421
|
+
return `service: running under ${plan.supervisor}
|
|
3422
|
+
`;
|
|
3423
|
+
case "installed":
|
|
3424
|
+
return `service: installed but NOT running (${state.detail}) \u2014 this machine is on rosters and serving nothing. See ${plan.logPath}
|
|
3425
|
+
`;
|
|
3426
|
+
case "absent":
|
|
3427
|
+
return `service: not installed \u2014 jobs only run while \`byollm run\` is open (\`byollm install\` fixes that)
|
|
3428
|
+
`;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3104
3431
|
async function commandName(paths, args, io) {
|
|
3105
3432
|
const next = args[0];
|
|
3106
3433
|
if (next === void 0) {
|
|
@@ -3108,8 +3435,8 @@ async function commandName(paths, args, io) {
|
|
|
3108
3435
|
`);
|
|
3109
3436
|
return 0;
|
|
3110
3437
|
}
|
|
3111
|
-
await
|
|
3112
|
-
await
|
|
3438
|
+
await mkdir8(dirname8(paths.label), { recursive: true });
|
|
3439
|
+
await writeFile8(paths.label, `${next.slice(0, 120)}
|
|
3113
3440
|
`, { mode: 384 });
|
|
3114
3441
|
io.out(
|
|
3115
3442
|
`This machine will pair as ${next.slice(0, 120)}.
|
|
@@ -3446,7 +3773,7 @@ function report(origin, event, io) {
|
|
|
3446
3773
|
break;
|
|
3447
3774
|
}
|
|
3448
3775
|
}
|
|
3449
|
-
async function commandStatus(paths, io) {
|
|
3776
|
+
async function commandStatus(paths, io, service) {
|
|
3450
3777
|
const { loaded, ingress, allowlist, budgets, spend } = await context(paths);
|
|
3451
3778
|
const pairings = new Pairings(paths.pairings);
|
|
3452
3779
|
await pairings.load();
|
|
@@ -3459,8 +3786,9 @@ async function commandStatus(paths, io) {
|
|
|
3459
3786
|
`
|
|
3460
3787
|
);
|
|
3461
3788
|
io.out(`state: ${paused ? "PAUSED" : "running"}
|
|
3462
|
-
|
|
3463
3789
|
`);
|
|
3790
|
+
io.out(await supervisionLine(paths, service));
|
|
3791
|
+
io.out("\n");
|
|
3464
3792
|
io.out("paired apps\n");
|
|
3465
3793
|
const list = pairings.list();
|
|
3466
3794
|
if (list.length === 0) {
|
|
@@ -3585,15 +3913,15 @@ function indent(text) {
|
|
|
3585
3913
|
return text.split("\n").map((line) => ` ${line}`).join("\n");
|
|
3586
3914
|
}
|
|
3587
3915
|
async function commandPause(paths, pause, io) {
|
|
3588
|
-
await
|
|
3916
|
+
await mkdir8(paths.root, { recursive: true });
|
|
3589
3917
|
if (pause) {
|
|
3590
|
-
await
|
|
3918
|
+
await writeFile8(paths.pauseFlag, `${(/* @__PURE__ */ new Date()).toISOString()}
|
|
3591
3919
|
`);
|
|
3592
3920
|
io.out(
|
|
3593
3921
|
"paused \u2014 no new work will be claimed. `byollm resume` to start again.\n"
|
|
3594
3922
|
);
|
|
3595
3923
|
} else {
|
|
3596
|
-
await
|
|
3924
|
+
await rm5(paths.pauseFlag, { force: true });
|
|
3597
3925
|
io.out("resumed\n");
|
|
3598
3926
|
}
|
|
3599
3927
|
return 0;
|
|
@@ -3769,8 +4097,8 @@ Offer ${backendKey} to ${scope === "public" ? "anyone" : "people you have allowe
|
|
|
3769
4097
|
...cost === "metered" && !widening && backend.spend !== void 0 ? { spend: { ...backend.spend, acknowledged: false } } : {}
|
|
3770
4098
|
};
|
|
3771
4099
|
}
|
|
3772
|
-
await
|
|
3773
|
-
await
|
|
4100
|
+
await mkdir8(dirname8(paths.config), { recursive: true });
|
|
4101
|
+
await writeFile8(paths.config, `${JSON.stringify(result.data, null, 2)}
|
|
3774
4102
|
`);
|
|
3775
4103
|
const written = result.data.backends[backendKey].spend?.dailyCapCents;
|
|
3776
4104
|
io.out(
|
|
@@ -3999,7 +4327,7 @@ async function main(argv) {
|
|
|
3999
4327
|
}
|
|
4000
4328
|
|
|
4001
4329
|
// src/index.ts
|
|
4002
|
-
var DAEMON_VERSION = "0.1.0-alpha.
|
|
4330
|
+
var DAEMON_VERSION = "0.1.0-alpha.40";
|
|
4003
4331
|
function daemonVersion() {
|
|
4004
4332
|
return {
|
|
4005
4333
|
daemon: DAEMON_VERSION,
|
|
@@ -4051,4 +4379,4 @@ export {
|
|
|
4051
4379
|
runCli,
|
|
4052
4380
|
main
|
|
4053
4381
|
};
|
|
4054
|
-
//# sourceMappingURL=chunk-
|
|
4382
|
+
//# sourceMappingURL=chunk-RYUKSHXG.js.map
|