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 CHANGED
@@ -1,5 +1,5 @@
1
1
  > [!WARNING]
2
- > **Alpha (`0.1.0-alpha.39`) — under active development. Don't use this yet.**
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.39` is that release, whole.
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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "./chunk-GBQBJAT7.js";
4
+ } from "./chunk-RYUKSHXG.js";
5
5
 
6
6
  // src/bin.ts
7
7
  process.exitCode = await main(process.argv.slice(2));
@@ -96,9 +96,9 @@ function normalizeOrigin(input) {
96
96
  }
97
97
 
98
98
  // src/cli.ts
99
- import { mkdir as mkdir7, readFile as readFile8, rm as rm4, stat as stat2, writeFile as writeFile7 } from "fs/promises";
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 dirname7 } from "path";
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
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 mkdir7(dirname7(paths.label), { recursive: true });
3112
- await writeFile7(paths.label, `${next.slice(0, 120)}
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 mkdir7(paths.root, { recursive: true });
3916
+ await mkdir8(paths.root, { recursive: true });
3589
3917
  if (pause) {
3590
- await writeFile7(paths.pauseFlag, `${(/* @__PURE__ */ new Date()).toISOString()}
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 rm4(paths.pauseFlag, { force: true });
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 mkdir7(dirname7(paths.config), { recursive: true });
3773
- await writeFile7(paths.config, `${JSON.stringify(result.data, null, 2)}
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.39";
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-GBQBJAT7.js.map
4382
+ //# sourceMappingURL=chunk-RYUKSHXG.js.map