mainflow 0.32.1 → 0.33.0-beta.1

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/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { B as parseRef, H as refExample, V as parseUntil, Y as stampMs, k as UNTIL_FORMS } from "./dist-IdbnCDqM.js";
3
- import { B as checkHubName, H as loadHub, J as TASK_FILE, Q as nodeStorage, S as readSession, V as HubError, X as nowMinute, Y as requireSlug, _ as untilState, ct as findHubRoot, d as retroReportFromReceiver, dt as DATA_DIR, et as MAX_FILE_BYTES, f as receiverFromEnv, ft as WriteError, g as initHub, l as migrateHub, p as RETRY_RULES, q as MAINLINE_FILE, u as retroReport, v as duplicateClaimLines, x as loadSessions, y as sessionBriefing, z as applyOperation } from "./host-C7GKIjSc.js";
3
+ import { $ as MAX_FILE_BYTES, B as checkHubName, H as loadHub, S as readSession, V as HubError, Y as nodeStorage, _ as untilState, ct as TASK_FILE, d as retroReportFromReceiver, dt as findHubRoot, f as receiverFromEnv, g as initHub, ht as WriteError, l as migrateHub, lt as requireSlug, mt as DATA_DIR, p as RETRY_RULES, q as nowMinute, st as MAINLINE_FILE, u as retroReport, v as duplicateClaimLines, x as loadSessions, y as sessionBriefing, z as applyOperation } from "./host-CObkJQmr.js";
4
4
  import { t as listProgress } from "./progress-1BfPg2zN.js";
5
- import { C as hubName, O as syncPaths, S as earlierToken, T as SETTINGS_FILE, _ as readRemote, a as remoteMode, b as ServerError, c as planFetch, d as DaemonRunning, f as DaemonUnavailable, g as silentHint, h as readDaemon, i as queuedCount, l as planFlush, m as probeDaemon, n as hubWriter, o as fetchDenial, p as callDaemon, r as writtenLines, s as hookAnswer, t as CONFIRM_MS, u as startDaemon, v as oversizedFiles, w as syncSettings, x as ENV, y as ServerApi } from "./operation-C0dUHUHg.js";
5
+ import { A as syncPaths, C as ENV, D as SETTINGS_FILE, E as syncSettings, S as ServerError, T as hubName, _ as readDaemon, a as remoteMode, b as oversizedFiles, c as planAnnounce, d as toolCallOf, f as startDaemon, g as probeDaemon, h as callDaemon, i as queuedCount, l as planFetch, m as DaemonUnavailable, n as hubWriter, o as fetchDenial, p as DaemonRunning, r as writtenLines, s as hookAnswer, t as CONFIRM_MS, u as planFlush, v as silentHint, w as earlierToken, x as ServerApi, y as readRemote } from "./operation-B2pq2Q9z.js";
6
6
  import { COMMAND_SPECS, OPTIONS } from "./facts.js";
7
7
  import { hookFallback, parsePayload, runHook } from "./hooks.js";
8
- import { c as watchHubGone, l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-6839iAsc.js";
8
+ import { c as watchHubGone, l as CLI_VERSION, r as launchUi, s as startUiInBackground } from "./launch-BemxyV9P.js";
9
9
  import { randomBytes } from "node:crypto";
10
10
  import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
11
11
  import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -90,11 +90,22 @@ async function syncFlush(root, hook) {
90
90
  console.error("✗ mainflow sync is not running for this hub");
91
91
  return 1;
92
92
  }
93
- const plan = hook ? planFlush(root, payload) : { skip: false };
94
- if (plan.skip) return 0;
93
+ let body = {};
94
+ if (hook) {
95
+ const plan = planFlush(root, payload);
96
+ if (plan.skip) return 0;
97
+ const call = toolCallOf(payload);
98
+ body = {
99
+ ...plan.edit ? { edit: plan.edit } : {
100
+ tool: true,
101
+ ...plan.path === void 0 ? {} : { path: plan.path }
102
+ },
103
+ ...call ? { call } : {}
104
+ };
105
+ }
95
106
  let result;
96
107
  try {
97
- result = await callDaemon(daemon, "/flush", plan.edit ? { edit: plan.edit } : {}, 3e4);
108
+ result = await callDaemon(daemon, "/flush", body, 3e4);
98
109
  } catch (error) {
99
110
  if (hook && error instanceof DaemonUnavailable) return 0;
100
111
  throw error;
@@ -137,7 +148,8 @@ function fetchSpec(root, target) {
137
148
  * the hook for it (Claude Code answers an Edit of a missing file before its hooks). A Read then goes ahead; a write is
138
149
  * stopped with the reason, so the agent reads the file before writing over it. When it cannot be
139
150
  * downloaded, or no sync client runs, the tool is stopped with the reason, so the agent does not take the file for one
140
- * that does not exist. Anything else answers nothing.
151
+ * that does not exist. An Edit of one replacement of a synced file here is announced to the sync client. Anything else
152
+ * answers nothing.
141
153
  */
142
154
  async function syncFetch(root, target, hook) {
143
155
  if (hook) return syncFetchHook(root, readPayload());
@@ -173,9 +185,29 @@ async function syncFetch(root, target, hook) {
173
185
  else console.log(`✓ downloaded ${result.fetched.length} file${result.fetched.length === 1 ? "" : "s"}`);
174
186
  return 0;
175
187
  }
188
+ /** How long the PreToolUse hook waits for the sync client to take an Edit's announcement; the Edit runs either way. */
189
+ const ANNOUNCE_MS = 2e3;
190
+ /**
191
+ * Tell the running sync client of the Edit in `payload` before it runs, so the change it makes waits for its report
192
+ * rather than being taken for a rewrite of an older version (docs/sync.md "等 Edit 的回報"). Silent whatever happens:
193
+ * without a sync client, or with one older than the announcement, which answers 404, the change is sent as unannounced.
194
+ */
195
+ async function announceEdit(root, payload) {
196
+ const edit = planAnnounce(root, payload);
197
+ const daemon = edit ? readDaemon(root) : null;
198
+ if (!edit || !daemon) return 0;
199
+ try {
200
+ const call = toolCallOf(payload);
201
+ await callDaemon(daemon, "/announce", {
202
+ edit,
203
+ ...call ? { call } : {}
204
+ }, ANNOUNCE_MS);
205
+ } catch {}
206
+ return 0;
207
+ }
176
208
  async function syncFetchHook(root, payload) {
177
209
  const plan = planFetch(root, payload);
178
- if (!plan) return 0;
210
+ if (!plan) return announceEdit(root, payload);
179
211
  const deny = (reason) => {
180
212
  console.log(fetchDenial(reason));
181
213
  return 0;
@@ -193,7 +225,11 @@ async function syncFetchHook(root, payload) {
193
225
  if (busy) return deny(`.mainflow/${plan.path} is only on the sync server and is not downloaded yet: mainflow sync did not answer within ${FETCH_MS / 1e3} s, as it is busy, such as with a large snapshot. Try again shortly, or run mainflow sync fetch ${plan.path}; the file exists, do not take it for missing.`);
194
226
  return deny(`.mainflow/${plan.path} is only on the sync server and is not downloaded here, and mainflow sync is not running, so it cannot be downloaded now. Start mainflow sync and run mainflow sync fetch ${plan.path}; the file exists, do not take it for missing.`);
195
227
  }
196
- if (result.error) return deny(`.mainflow/${plan.path} is only on the sync server and could not be downloaded (${result.error}). Try again once mainflow sync status says online; the file exists, do not take it for missing.`);
228
+ if (result.error) {
229
+ const where = `.mainflow/${plan.path} is only on the sync server and could not be downloaded (${result.error}). The file exists, do not take it for missing.`;
230
+ if (result.error.includes("is offline")) return deny(`${where} Try again once mainflow sync status says online.`);
231
+ return deny(`${where} Do not wait for mainflow sync status to say online: the reason above is what holds the file back. If it is a full disk or a folder this machine cannot write, free space or fix the permission, then run mainflow sync fetch ${plan.path}. If the content is damaged or the server no longer holds it, mainflow sync tries again by itself as the reason says; run mainflow sync fetch ${plan.path} to try at once.`);
232
+ }
197
233
  if (!result.fetched.includes(plan.path)) return 0;
198
234
  if (plan.write) return deny(`.mainflow/${plan.path} was only on the sync server and is downloaded now. Read it before writing to it, so the write starts from what it holds.`);
199
235
  return 0;
package/dist/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $ as describeRequest, j as configSchema } from "./dist-IdbnCDqM.js";
2
- import { D as endsWithMarker, E as decorateReply, H as loadHub, O as headerLine, S as readSession, T as matchGrants, V as HubError, Z as readYaml, b as turnReminder, ct as findHubRoot, dt as DATA_DIR, i as hostName, k as mayDecorate, lt as worktreesOf, st as currentBranch, w as grantScope, x as loadSessions, y as sessionBriefing } from "./host-C7GKIjSc.js";
3
- import { n as hubWriter, r as writtenLines } from "./operation-C0dUHUHg.js";
2
+ import { D as endsWithMarker, E as decorateReply, H as loadHub, J as readYaml, O as headerLine, S as readSession, T as matchGrants, V as HubError, b as turnReminder, dt as findHubRoot, ft as worktreesOf, i as hostName, k as mayDecorate, mt as DATA_DIR, ut as currentBranch, w as grantScope, x as loadSessions, y as sessionBriefing } from "./host-CObkJQmr.js";
3
+ import { n as hubWriter, r as writtenLines } from "./operation-B2pq2Q9z.js";
4
4
  import { resolveFixed, scanCommand, scopedCwd } from "./grant-commands.js";
5
5
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
@@ -310,6 +310,59 @@ function editFrontMatter(draft, path, schema, mutate, expectedVersion) {
310
310
  return next;
311
311
  }
312
312
  //#endregion
313
+ //#region ../core/dist/ops/resolve.js
314
+ const MAINLINES_DIR = "mainlines";
315
+ const CONFIG_FILE = "config.yaml";
316
+ const ISSUES_DIR = "issues";
317
+ const FINDINGS_DIR = "findings";
318
+ const SESSIONS_DIR = "local/sessions";
319
+ /** The document inside each mainline and task directory: front matter for attributes, body for prose. */
320
+ const MAINLINE_FILE = "mainline.md";
321
+ const TASK_FILE = "task.md";
322
+ function requireRef(input, kind) {
323
+ const ref = parseRef(input);
324
+ if (ref?.kind !== kind) throw new WriteError(`expected a ${kind} reference like ${refExample(kind)}, got "${input}"`);
325
+ return ref;
326
+ }
327
+ function requireSlug(slug) {
328
+ if (!SLUG.test(slug)) throw new WriteError(`slug "${slug}" must be kebab-case, e.g. mainflow-rebuild`);
329
+ }
330
+ function requireOneOf(value, allowed, what) {
331
+ if (!allowed.includes(value)) throw new WriteError(`${what} "${value}" must be one of: ${allowed.join(", ")}`);
332
+ return value;
333
+ }
334
+ const readConfigIn = (hub) => readYamlIn(hub, CONFIG_FILE, configSchema);
335
+ /** The entry directory whose name starts with `{id}-` inside `parent`. */
336
+ function findEntryDirIn(hub, parent, id) {
337
+ const entry = hub.list(parent).find((e) => e.dir && ENTRY_DIR.exec(e.name)?.[1] === id);
338
+ return entry ? `${parent}/${entry.name}` : null;
339
+ }
340
+ /** Entry ids (m001, t002, d003) found among the names in `dir`. */
341
+ const idsIn = (hub, dir) => hub.list(dir).map((e) => ENTRY_DIR.exec(e.name)?.[1]).filter((id) => !!id);
342
+ function mainlineDirIn(hub, id) {
343
+ const dir = findEntryDirIn(hub, MAINLINES_DIR, id);
344
+ if (!dir) throw new WriteError(`mainline ${id} not found; run "mainflow status --all" to list mainlines`);
345
+ return dir;
346
+ }
347
+ function taskDirIn(hub, mainline, task) {
348
+ const dir = findEntryDirIn(hub, `${mainlineDirIn(hub, mainline)}/tasks`, task);
349
+ if (!dir) throw new WriteError(`task ${mainline}/${task} not found`);
350
+ return dir;
351
+ }
352
+ const mainlineFileIn = (hub, id) => `${mainlineDirIn(hub, id)}/${MAINLINE_FILE}`;
353
+ const taskFileIn = (hub, mainline, task) => `${taskDirIn(hub, mainline, task)}/${TASK_FILE}`;
354
+ /** The Markdown file named `{id}-….md` in `dir`, or null. */
355
+ function entryFileIn(hub, dir, id) {
356
+ const name = hub.list(dir).find((e) => e.name.startsWith(`${id}-`) && e.name.endsWith(".md"))?.name;
357
+ return name ? `${dir}/${name}` : null;
358
+ }
359
+ function decisionFileIn(hub, mainline, decision) {
360
+ const file = entryFileIn(hub, `${mainlineDirIn(hub, mainline)}/decisions`, decision);
361
+ if (!file) throw new WriteError(`decision ${mainline}/${decision} not found`);
362
+ return file;
363
+ }
364
+ const sessionFileIn = (id) => `${SESSIONS_DIR}/${id}.yaml`;
365
+ //#endregion
313
366
  //#region ../core/dist/ops/protocol.js
314
367
  /** `now` of a request: a local minute and its offset from UTC, `Z` for UTC itself. */
315
368
  const REQUEST_TIME = new RegExp(`^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(${OFFSET})$`);
@@ -334,8 +387,18 @@ const ROUTES = {
334
387
  request: (hub) => `/hub/${hub}/request`,
335
388
  /** POST: one batch of the hub's snapshot (SnapshotRequest, answered with SnapshotBatch). PUT: upload a whole hub (UploadRequest) */
336
389
  snapshot: (hub) => `/hub/${hub}/snapshot`,
337
- /** GET `?protocol=3` with `Upgrade: websocket`: receive every broadcast of the hub (ServerBroadcast) */
338
- socket: (hub) => `/hub/${hub}/ws`
390
+ /**
391
+ * GET `?protocol=3` with `Upgrade: websocket`: receive every broadcast of the hub (ServerBroadcast); `&blobs=true` takes
392
+ * the binary files too (SnapshotRequest.blobs)
393
+ */
394
+ socket: (hub) => `/hub/${hub}/ws`,
395
+ /**
396
+ * PUT: upload the raw bytes of a binary file whose sha256 is `hash`, with Content-Length, answered with BlobUploaded.
397
+ * Content the server keeps already is answered without its body being read, so a body that is not of `hash` is not
398
+ * refused then: the server holds the right content already. GET: download them. Neither carries the protocol version:
399
+ * the content is named by its own hash.
400
+ */
401
+ blob: (hub, hash) => `/hub/${hub}/blob/${hash}`
339
402
  };
340
403
  /**
341
404
  * The service token of Cloudflare Access, which stands in front of the sync server and lets through only the requests
@@ -346,6 +409,26 @@ const ACCESS_HEADERS = {
346
409
  clientId: "CF-Access-Client-Id",
347
410
  clientSecret: "CF-Access-Client-Secret"
348
411
  };
412
+ /** The hash of a binary file: the sha256 of its raw bytes in lowercase hex, apart from the sha1 of a text file's content. */
413
+ const BLOB_HASH = /^[0-9a-f]{64}$/;
414
+ /**
415
+ * The largest binary file the sync server keeps, in bytes: 50 MiB, half the 100 MB a request body may hold on the
416
+ * Workers Free plan. The content goes to R2, so the 2 MB of a Durable Object row does not bound it.
417
+ */
418
+ const MAX_BLOB_BYTES = 52428800;
419
+ /** The documents the hub reads as text besides config.yaml: Markdown and YAML documents, the operation logs and .gitignore files. */
420
+ const TEXT_ONLY = [
421
+ /\.(md|ya?ml)$/i,
422
+ /^ops\/[^/]+\.log$/,
423
+ /(^|\/)\.gitignore$/
424
+ ];
425
+ /**
426
+ * Whether the hub reads the file at `path`, relative to the data directory, as text: config.yaml, Markdown and YAML
427
+ * documents, the operation logs (ops/*.log) and .gitignore files. One of them that is not UTF-8 can only be one broken,
428
+ * so it is never kept as a binary file: the sync server refuses it, and the sync client leaves it as it is and tells the
429
+ * writer.
430
+ */
431
+ const readsAsText = (path) => path === "config.yaml" || TEXT_ONLY.some((pattern) => pattern.test(path));
349
432
  /**
350
433
  * The largest text the sync server keeps of one file, in UTF-8 bytes: a SQLite row of a Durable Object holds at most
351
434
  * 2 MB, path and columns included. The server refuses a write or an upload that would hold a larger file; the sync client
@@ -527,59 +610,6 @@ function readFrontMatter(file, schema) {
527
610
  };
528
611
  }
529
612
  //#endregion
530
- //#region ../core/dist/ops/resolve.js
531
- const MAINLINES_DIR = "mainlines";
532
- const CONFIG_FILE = "config.yaml";
533
- const ISSUES_DIR = "issues";
534
- const FINDINGS_DIR = "findings";
535
- const SESSIONS_DIR = "local/sessions";
536
- /** The document inside each mainline and task directory: front matter for attributes, body for prose. */
537
- const MAINLINE_FILE = "mainline.md";
538
- const TASK_FILE = "task.md";
539
- function requireRef(input, kind) {
540
- const ref = parseRef(input);
541
- if (ref?.kind !== kind) throw new WriteError(`expected a ${kind} reference like ${refExample(kind)}, got "${input}"`);
542
- return ref;
543
- }
544
- function requireSlug(slug) {
545
- if (!SLUG.test(slug)) throw new WriteError(`slug "${slug}" must be kebab-case, e.g. mainflow-rebuild`);
546
- }
547
- function requireOneOf(value, allowed, what) {
548
- if (!allowed.includes(value)) throw new WriteError(`${what} "${value}" must be one of: ${allowed.join(", ")}`);
549
- return value;
550
- }
551
- const readConfigIn = (hub) => readYamlIn(hub, CONFIG_FILE, configSchema);
552
- /** The entry directory whose name starts with `{id}-` inside `parent`. */
553
- function findEntryDirIn(hub, parent, id) {
554
- const entry = hub.list(parent).find((e) => e.dir && ENTRY_DIR.exec(e.name)?.[1] === id);
555
- return entry ? `${parent}/${entry.name}` : null;
556
- }
557
- /** Entry ids (m001, t002, d003) found among the names in `dir`. */
558
- const idsIn = (hub, dir) => hub.list(dir).map((e) => ENTRY_DIR.exec(e.name)?.[1]).filter((id) => !!id);
559
- function mainlineDirIn(hub, id) {
560
- const dir = findEntryDirIn(hub, MAINLINES_DIR, id);
561
- if (!dir) throw new WriteError(`mainline ${id} not found; run "mainflow status --all" to list mainlines`);
562
- return dir;
563
- }
564
- function taskDirIn(hub, mainline, task) {
565
- const dir = findEntryDirIn(hub, `${mainlineDirIn(hub, mainline)}/tasks`, task);
566
- if (!dir) throw new WriteError(`task ${mainline}/${task} not found`);
567
- return dir;
568
- }
569
- const mainlineFileIn = (hub, id) => `${mainlineDirIn(hub, id)}/${MAINLINE_FILE}`;
570
- const taskFileIn = (hub, mainline, task) => `${taskDirIn(hub, mainline, task)}/${TASK_FILE}`;
571
- /** The Markdown file named `{id}-….md` in `dir`, or null. */
572
- function entryFileIn(hub, dir, id) {
573
- const name = hub.list(dir).find((e) => e.name.startsWith(`${id}-`) && e.name.endsWith(".md"))?.name;
574
- return name ? `${dir}/${name}` : null;
575
- }
576
- function decisionFileIn(hub, mainline, decision) {
577
- const file = entryFileIn(hub, `${mainlineDirIn(hub, mainline)}/decisions`, decision);
578
- if (!file) throw new WriteError(`decision ${mainline}/${decision} not found`);
579
- return file;
580
- }
581
- const sessionFileIn = (id) => `${SESSIONS_DIR}/${id}.yaml`;
582
- //#endregion
583
613
  //#region ../core/dist/resolve.js
584
614
  /** The absolute path of a path inside the hub's data directory. */
585
615
  const onDisk = (root, path) => join(root, DATA_DIR, path);
@@ -7356,4 +7386,4 @@ function openInApp(hub, target, closeAfterMs = 150) {
7356
7386
  return true;
7357
7387
  }
7358
7388
  //#endregion
7359
- export { ACCESS_HEADERS as $, attributeTrace as A, checkHubName as B, transcriptPath as C, endsWithMarker as D, decorateReply as E, renumberFiles as F, linksInto as G, loadHub as H, renumberPath as I, TASK_FILE as J, refIndex as K, renumberText as L, transcriptTitle as M, applyOffline as N, headerLine as O, renumberRequest as P, nodeStorage as Q, scopeOfPath as R, readSession as S, matchGrants as T, dependencyGraph as U, HubError as V, mainlineEdges as W, nowMinute as X, requireSlug as Y, readYaml as Z, untilState as _, openInApp as a, requestTime as at, turnReminder as b, syncHost as c, findHubRoot as ct, retroReportFromReceiver as d, DATA_DIR as dt, MAX_FILE_BYTES as et, receiverFromEnv as f, WriteError as ft, initHub as g, setArchivedMany as h, hostName as i, exceedsFileLimit as it, traceTranscript as j, mayDecorate as k, migrateHub as l, worktreesOf as lt, ARCHIVE_KINDS as m, splitFrontMatter as mt, DEFAULT_UI_PORT as n, SOCKET_MAX_AGE_CLOSE as nt, removeHostLink as o, textBytes as ot, RETRY_RULES as p, contentHash as pt, MAINLINE_FILE as q, caddySites as r, comparePaths as rt, siteBlock as s, currentBranch as st, APP_BUNDLE_ID as t, ROUTES as tt, retroReport as u, ConflictError as ut, duplicateClaimLines as v, grantScope as w, loadSessions as x, sessionBriefing as y, applyOperation as z };
7389
+ export { MAX_FILE_BYTES as $, attributeTrace as A, checkHubName as B, transcriptPath as C, endsWithMarker as D, decorateReply as E, renumberFiles as F, linksInto as G, loadHub as H, renumberPath as I, readYaml as J, refIndex as K, renumberText as L, transcriptTitle as M, applyOffline as N, headerLine as O, renumberRequest as P, MAX_BLOB_BYTES as Q, scopeOfPath as R, readSession as S, matchGrants as T, dependencyGraph as U, HubError as V, mainlineEdges as W, ACCESS_HEADERS as X, nodeStorage as Y, BLOB_HASH as Z, untilState as _, splitFrontMatter as _t, openInApp as a, requestTime as at, turnReminder as b, syncHost as c, TASK_FILE as ct, retroReportFromReceiver as d, findHubRoot as dt, ROUTES as et, receiverFromEnv as f, worktreesOf as ft, initHub as g, contentHash as gt, setArchivedMany as h, WriteError as ht, hostName as i, readsAsText as it, traceTranscript as j, mayDecorate as k, migrateHub as l, requireSlug as lt, ARCHIVE_KINDS as m, DATA_DIR as mt, DEFAULT_UI_PORT as n, comparePaths as nt, removeHostLink as o, textBytes as ot, RETRY_RULES as p, ConflictError as pt, nowMinute as q, caddySites as r, exceedsFileLimit as rt, siteBlock as s, MAINLINE_FILE as st, APP_BUNDLE_ID as t, SOCKET_MAX_AGE_CLOSE as tt, retroReport as u, currentBranch as ut, duplicateClaimLines as v, grantScope as w, loadSessions as x, sessionBriefing as y, applyOperation as z };
package/dist/host.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as openInApp, c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, r as caddySites, s as siteBlock, t as APP_BUNDLE_ID } from "./host-C7GKIjSc.js";
1
+ import { a as openInApp, c as syncHost, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink, r as caddySites, s as siteBlock, t as APP_BUNDLE_ID } from "./host-CObkJQmr.js";
2
2
  export { APP_BUNDLE_ID, DEFAULT_UI_PORT, caddySites, hostName, openInApp, removeHostLink, siteBlock, syncHost };
@@ -1,4 +1,4 @@
1
- import { c as syncHost, dt as DATA_DIR, ft as WriteError, i as hostName, n as DEFAULT_UI_PORT, o as removeHostLink } from "./host-C7GKIjSc.js";
1
+ import { c as syncHost, ht as WriteError, i as hostName, mt as DATA_DIR, n as DEFAULT_UI_PORT, o as removeHostLink } from "./host-CObkJQmr.js";
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { spawn, spawnSync } from "node:child_process";
@@ -176,7 +176,7 @@ async function launchUi(root, hub, configured, options) {
176
176
  }
177
177
  let server;
178
178
  if (!reuse) {
179
- const { serveUi } = await import("./ui-Bx2wUBnA.js");
179
+ const { serveUi } = await import("./ui-CFLjhYJ9.js");
180
180
  server = await serveUi(root, choice.port);
181
181
  writeUiRecord(root, {
182
182
  port: choice.port,
package/dist/launch.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as portCandidates, c as watchHubGone, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-6839iAsc.js";
1
+ import { a as portCandidates, c as watchHubGone, i as networkProbe, n as choosePort, o as readUiRecord, r as launchUi, s as startUiInBackground, t as PORT_SPAN } from "./launch-BemxyV9P.js";
2
2
  export { PORT_SPAN, choosePort, launchUi, networkProbe, portCandidates, readUiRecord, startUiInBackground, watchHubGone };