frizz 0.1.0 → 0.2.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/dist/frizz.js CHANGED
@@ -1803,6 +1803,131 @@ var init_migrate_fray = __esm({
1803
1803
  }
1804
1804
  });
1805
1805
 
1806
+ // packages/server/src/project-root.ts
1807
+ import { createHash as createHash3, randomUUID as randomUUID4 } from "node:crypto";
1808
+ import { closeSync as closeSync3, existsSync as existsSync3, fsyncSync as fsyncSync3, mkdirSync as mkdirSync5, openSync as openSync4, readFileSync as readFileSync5, renameSync as renameSync5, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "node:fs";
1809
+ import { homedir as homedir6 } from "node:os";
1810
+ import { dirname as dirname4, join as join8, parse, resolve as resolve3 } from "node:path";
1811
+ function projectIdPath(root) {
1812
+ return join8(root, FRIZZ_DIR, ID_FILE);
1813
+ }
1814
+ function readProjectIdFile(root) {
1815
+ let raw;
1816
+ try {
1817
+ raw = readFileSync5(projectIdPath(root), "utf8");
1818
+ } catch {
1819
+ return void 0;
1820
+ }
1821
+ try {
1822
+ return validateProjectId(raw.trim());
1823
+ } catch {
1824
+ throw new Error(`${projectIdPath(root)} is invalid; expected exactly one UUID`);
1825
+ }
1826
+ }
1827
+ function writeProjectIdFile(root, id) {
1828
+ const dir = join8(root, FRIZZ_DIR);
1829
+ mkdirSync5(dir, { recursive: true });
1830
+ const ignore = join8(dir, SELF_IGNORE);
1831
+ if (!existsSync3(ignore)) {
1832
+ try {
1833
+ writeFileSync5(ignore, "*\n", { flag: "wx" });
1834
+ } catch {
1835
+ }
1836
+ }
1837
+ const path = projectIdPath(root);
1838
+ const temp = join8(dir, `.${ID_FILE}.${process.pid}.${randomUUID4()}.tmp`);
1839
+ let fd;
1840
+ try {
1841
+ fd = openSync4(temp, "wx", 384);
1842
+ writeFileSync5(fd, `${id}
1843
+ `, "utf8");
1844
+ fsyncSync3(fd);
1845
+ closeSync3(fd);
1846
+ fd = void 0;
1847
+ renameSync5(temp, path);
1848
+ } catch (error) {
1849
+ if (fd !== void 0) {
1850
+ try {
1851
+ closeSync3(fd);
1852
+ } catch {
1853
+ }
1854
+ }
1855
+ try {
1856
+ rmSync5(temp, { force: true });
1857
+ } catch {
1858
+ }
1859
+ throw error;
1860
+ }
1861
+ return id;
1862
+ }
1863
+ function projectRootLockName(root) {
1864
+ return `identity-path-${createHash3("sha256").update(root).digest("hex")}.lock`;
1865
+ }
1866
+ function ensureProjectIdFile(root, home = homedir6(), seed) {
1867
+ const existing = readProjectIdFile(root);
1868
+ if (existing) return existing;
1869
+ const release = acquireNamedLaunchLockSync(home, projectRootLockName(root));
1870
+ try {
1871
+ const raced = readProjectIdFile(root);
1872
+ if (raced) return raced;
1873
+ return writeProjectIdFile(root, seed ? validateProjectId(seed) : randomUUID4());
1874
+ } finally {
1875
+ release();
1876
+ }
1877
+ }
1878
+ function isNotAGitWorktree(error) {
1879
+ const code = error?.code;
1880
+ if (code === "ENOENT" || code === "EACCES") return true;
1881
+ if (!error || typeof error !== "object" || !("stderr" in error)) return false;
1882
+ const stderr = String(error.stderr);
1883
+ return /not a git repository/iu.test(stderr) || /must be run in a work ?tree/iu.test(stderr);
1884
+ }
1885
+ function hasAny(dir, names) {
1886
+ return names.some((name) => existsSync3(join8(dir, name)));
1887
+ }
1888
+ function discoverProjectRoot(cwd = process.cwd(), home = homedir6()) {
1889
+ let dir;
1890
+ try {
1891
+ dir = resolve3(cwd);
1892
+ } catch {
1893
+ return resolve3(cwd);
1894
+ }
1895
+ const stop = resolve3(home);
1896
+ const filesystemRoot = parse(dir).root;
1897
+ for (let at = dir; ; at = dirname4(at)) {
1898
+ if (at === stop || at === filesystemRoot) break;
1899
+ if (existsSync3(projectIdPath(at))) return at;
1900
+ if (hasAny(at, REPO_MARKERS)) return at;
1901
+ if (hasAny(at, PROJECT_MARKERS)) return at;
1902
+ if (dirname4(at) === at) break;
1903
+ }
1904
+ return dir;
1905
+ }
1906
+ var FRIZZ_DIR, ID_FILE, SELF_IGNORE, REPO_MARKERS, PROJECT_MARKERS;
1907
+ var init_project_root = __esm({
1908
+ "packages/server/src/project-root.ts"() {
1909
+ "use strict";
1910
+ init_project_identity();
1911
+ FRIZZ_DIR = ".frizz";
1912
+ ID_FILE = ".id";
1913
+ SELF_IGNORE = ".gitignore";
1914
+ REPO_MARKERS = [".git", ".jj", ".hg", ".svn"];
1915
+ PROJECT_MARKERS = [
1916
+ "package.json",
1917
+ "pyproject.toml",
1918
+ "go.mod",
1919
+ "Cargo.toml",
1920
+ "deno.json",
1921
+ "deno.jsonc",
1922
+ "composer.json",
1923
+ "Gemfile",
1924
+ "pom.xml",
1925
+ "build.gradle",
1926
+ "Makefile"
1927
+ ];
1928
+ }
1929
+ });
1930
+
1806
1931
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
1807
1932
  var util, objectUtil, ZodParsedType, getParsedType;
1808
1933
  var init_util = __esm({
@@ -7752,7 +7877,7 @@ ${DISPATCH_TASK_BANNER}
7752
7877
  });
7753
7878
 
7754
7879
  // packages/server/src/local-image.ts
7755
- import { readFileSync as readFileSync6, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
7880
+ import { readFileSync as readFileSync7, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
7756
7881
  import { extname, isAbsolute as isAbsolute2 } from "node:path";
7757
7882
  function resolveLocalImage(rawPath) {
7758
7883
  if (!rawPath || !isAbsolute2(rawPath)) return { status: 400 };
@@ -7766,7 +7891,7 @@ function resolveLocalImage(rawPath) {
7766
7891
  }
7767
7892
  try {
7768
7893
  if (!statSync4(real).isFile()) return { status: 404 };
7769
- return { status: 200, contentType, body: readFileSync6(real) };
7894
+ return { status: 200, contentType, body: readFileSync7(real) };
7770
7895
  } catch {
7771
7896
  return { status: 404 };
7772
7897
  }
@@ -7786,10 +7911,10 @@ var init_local_image = __esm({
7786
7911
  });
7787
7912
 
7788
7913
  // src/production.ts
7789
- import { readFileSync as readFileSync8 } from "node:fs";
7790
- import { homedir as homedir7 } from "node:os";
7914
+ import { readFileSync as readFileSync9 } from "node:fs";
7915
+ import { homedir as homedir8 } from "node:os";
7791
7916
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7792
- import { join as join10 } from "node:path";
7917
+ import { join as join11 } from "node:path";
7793
7918
 
7794
7919
  // src/browser.ts
7795
7920
  import { spawn, execFile } from "node:child_process";
@@ -7951,12 +8076,12 @@ function manifestIdFor(url) {
7951
8076
  return url.endsWith("/") ? url : `${url}/`;
7952
8077
  }
7953
8078
  function execFileP(cmd, args2) {
7954
- return new Promise((resolve5, reject) => {
8079
+ return new Promise((resolve6, reject) => {
7955
8080
  execFile(
7956
8081
  cmd,
7957
8082
  args2,
7958
8083
  { encoding: "utf8", timeout: 1e4 },
7959
- (err, stdout) => err ? reject(err) : resolve5(stdout)
8084
+ (err, stdout) => err ? reject(err) : resolve6(stdout)
7960
8085
  );
7961
8086
  });
7962
8087
  }
@@ -8035,9 +8160,9 @@ function openCdpSession(browserPath, dataPath) {
8035
8160
  cmdPipe.on("error", failAll);
8036
8161
  resPipe.on("error", failAll);
8037
8162
  child.on("exit", () => failAll(new Error("chrome exited before the CDP handshake completed")));
8038
- const call = (method, params = {}, timeoutMs = 2e4) => new Promise((resolve5, reject) => {
8163
+ const call = (method, params = {}, timeoutMs = 2e4) => new Promise((resolve6, reject) => {
8039
8164
  const id = ++seq;
8040
- pending.set(id, { resolve: resolve5, reject });
8165
+ pending.set(id, { resolve: resolve6, reject });
8041
8166
  cmdPipe.write(JSON.stringify({ id, method, params }) + "\0");
8042
8167
  setTimeout(() => {
8043
8168
  if (pending.has(id)) {
@@ -8050,15 +8175,15 @@ function openCdpSession(browserPath, dataPath) {
8050
8175
  await call("Browser.close").catch(() => {
8051
8176
  });
8052
8177
  if (child.exitCode !== null || child.signalCode !== null) return;
8053
- await new Promise((resolve5) => {
8178
+ await new Promise((resolve6) => {
8054
8179
  const t = setTimeout(() => {
8055
8180
  child.kill();
8056
- resolve5();
8181
+ resolve6();
8057
8182
  }, 1e4);
8058
8183
  t.unref();
8059
8184
  child.once("exit", () => {
8060
8185
  clearTimeout(t);
8061
- resolve5();
8186
+ resolve6();
8062
8187
  });
8063
8188
  });
8064
8189
  };
@@ -8537,13 +8662,14 @@ init_local_origin();
8537
8662
  init_boot_progress();
8538
8663
  init_frizz_paths();
8539
8664
  init_migrate_fray();
8665
+ init_project_root();
8540
8666
  init_logging();
8541
8667
  init_src();
8542
8668
  import { execFileSync as execFileSync4 } from "node:child_process";
8543
8669
  import { createServer } from "node:net";
8544
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, realpathSync as realpathSync3, writeFileSync as writeFileSync5 } from "node:fs";
8545
- import { homedir as homedir6, networkInterfaces } from "node:os";
8546
- import { basename as basename4, join as join8, resolve as resolve3 } from "node:path";
8670
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync6, realpathSync as realpathSync3, writeFileSync as writeFileSync6 } from "node:fs";
8671
+ import { homedir as homedir7, networkInterfaces } from "node:os";
8672
+ import { basename as basename4, join as join9, resolve as resolve4 } from "node:path";
8547
8673
  import { setTimeout as delay2 } from "node:timers/promises";
8548
8674
  var PORT_SCAN_COUNT = 100;
8549
8675
  var LAUNCH_TIMEOUT_MS = 3e4;
@@ -8711,40 +8837,41 @@ function networkUrls(port, host, interfaces = networkInterfaces) {
8711
8837
  }
8712
8838
  return urls;
8713
8839
  }
8714
- function resolveWorkspace(cwd = process.cwd(), home = homedir6(), env = process.env, { migrate = false } = {}) {
8840
+ function resolveWorkspace(cwd = process.cwd(), home = homedir7(), env = process.env, { migrate = false } = {}) {
8715
8841
  let gitRoot;
8716
8842
  try {
8717
8843
  gitRoot = execFileSync4("git", ["rev-parse", "--show-toplevel"], {
8718
8844
  cwd,
8719
8845
  encoding: "utf8",
8720
- stdio: ["ignore", "pipe", "ignore"]
8846
+ // stderr is CAPTURED, not ignored: it is the only thing that distinguishes "no worktree here"
8847
+ // from "this repository is broken", and those two must not be handled the same way.
8848
+ stdio: ["ignore", "pipe", "pipe"]
8721
8849
  }).trim();
8722
- } catch {
8723
- throw new Error(
8724
- `frizz-dev must be run inside a Git repository (cwd: ${cwd})`
8725
- );
8850
+ } catch (error) {
8851
+ if (!isNotAGitWorktree(error)) throw new Error("unable to resolve Git repository root");
8852
+ gitRoot = void 0;
8726
8853
  }
8727
8854
  if (migrate) migrateFrayGlobalRoots({ env, home });
8728
- const root0 = realpathSync3(gitRoot);
8855
+ const root0 = realpathSync3(gitRoot ?? discoverProjectRoot(cwd, home));
8729
8856
  if (migrate) migrateFrayProjectId(root0, { home });
8730
- const identity = resolveGitProjectIdentity(root0, home);
8731
- const root = identity.root;
8857
+ const identity = gitRoot ? resolveGitProjectIdentity(root0, home) : void 0;
8858
+ const root = identity?.root ?? root0;
8732
8859
  if (migrate) migrateFrayProjectDir(root);
8733
- const id = identity.id;
8860
+ const id = ensureProjectIdFile(root, home, identity?.id);
8734
8861
  const stateDir = projectStateDir(id, home);
8735
- mkdirSync5(stateDir, { recursive: true });
8862
+ mkdirSync6(stateDir, { recursive: true });
8736
8863
  const target2 = {
8737
8864
  projectId: id,
8738
8865
  projectDir: root,
8739
8866
  stateDir,
8740
- ...identity.scope === "worktree" ? { identityScope: "worktree" } : {}
8867
+ ...identity?.scope === "worktree" ? { identityScope: "worktree" } : {}
8741
8868
  };
8742
8869
  return {
8743
8870
  root,
8744
8871
  id,
8745
8872
  stateDir,
8746
8873
  name: basename4(root),
8747
- identityScope: identity.scope
8874
+ identityScope: identity?.scope ?? "repository"
8748
8875
  };
8749
8876
  }
8750
8877
  function workspaceLaunchTarget(workspace2) {
@@ -8775,7 +8902,7 @@ function workspaceFromLaunchTarget(target2, env = process.env) {
8775
8902
  function parseStatusFile(path, authoritative, expected2, adapter = defaultProcessPlatformAdapter) {
8776
8903
  try {
8777
8904
  const value = JSON.parse(
8778
- readFileSync5(path, "utf8")
8905
+ readFileSync6(path, "utf8")
8779
8906
  );
8780
8907
  if (!Number.isInteger(value.pid) || value.pid <= 0 || !Number.isInteger(value.port) || value.port < 1 || value.port > 65535)
8781
8908
  return null;
@@ -8803,12 +8930,12 @@ function liveWorkspaceOwner(stateDir, expected2, adapter = defaultProcessPlatfor
8803
8930
  if (authoritative && processGenerationIsStale(authoritative, adapter))
8804
8931
  return null;
8805
8932
  return parseStatusFile(
8806
- join8(stateDir, "dev-supervisor.lock"),
8933
+ join9(stateDir, "dev-supervisor.lock"),
8807
8934
  authoritative,
8808
8935
  expected2,
8809
8936
  adapter
8810
8937
  ) ?? parseStatusFile(
8811
- join8(stateDir, "server.lock"),
8938
+ join9(stateDir, "server.lock"),
8812
8939
  authoritative,
8813
8940
  expected2,
8814
8941
  adapter
@@ -8817,7 +8944,7 @@ function liveWorkspaceOwner(stateDir, expected2, adapter = defaultProcessPlatfor
8817
8944
  function readPreferredPort(stateDir) {
8818
8945
  try {
8819
8946
  const value = JSON.parse(
8820
- readFileSync5(join8(stateDir, "launcher.json"), "utf8")
8947
+ readFileSync6(join9(stateDir, "launcher.json"), "utf8")
8821
8948
  );
8822
8949
  return Number.isInteger(value.port) && value.port > 0 && value.port <= 65535 ? value.port : void 0;
8823
8950
  } catch {
@@ -8931,10 +9058,10 @@ init_project_launch();
8931
9058
  // packages/server/src/dev-supervisor.ts
8932
9059
  init_project_launch();
8933
9060
  import { fork } from "node:child_process";
8934
- import { randomUUID as randomUUID4 } from "node:crypto";
8935
- import { existsSync as existsSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync7 } from "node:fs";
9061
+ import { randomUUID as randomUUID5 } from "node:crypto";
9062
+ import { existsSync as existsSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
8936
9063
  import { createServer as createNetServer } from "node:net";
8937
- import { basename as basename5, dirname as dirname4, extname as extname2, isAbsolute as isAbsolute3, relative, resolve as resolve4, sep as sep2 } from "node:path";
9064
+ import { basename as basename5, dirname as dirname5, extname as extname2, isAbsolute as isAbsolute3, relative, resolve as resolve5, sep as sep2 } from "node:path";
8938
9065
  import { fileURLToPath } from "node:url";
8939
9066
  import watcher from "@parcel/watcher";
8940
9067
 
@@ -9309,8 +9436,8 @@ function createSupervisorShutdownHandler(options2) {
9309
9436
  );
9310
9437
  };
9311
9438
  }
9312
- var packagesDir = resolve4(import.meta.dirname, "..", "..");
9313
- var workspaceDir = resolve4(packagesDir, "..");
9439
+ var packagesDir = resolve5(import.meta.dirname, "..", "..");
9440
+ var workspaceDir = resolve5(packagesDir, "..");
9314
9441
  var INITIAL_BOOT_REASON = "initial boot";
9315
9442
  function defaultDevWatchRoots() {
9316
9443
  return [workspaceDir];
@@ -9320,17 +9447,17 @@ function isWithin(path, root) {
9320
9447
  return rel === "" || rel !== ".." && !rel.startsWith(`..${sep2}`) && !isAbsolute3(rel);
9321
9448
  }
9322
9449
  function ignoredDevPath(path) {
9323
- const parts = resolve4(path).split(sep2);
9450
+ const parts = resolve5(path).split(sep2);
9324
9451
  const name = parts.at(-1) ?? "";
9325
9452
  return parts.some((part) => GENERATED_DIRS.has(part) || part === "fixtures" || part.endsWith(".fixtures")) || /\.(?:test|spec)\.[^.]+$/.test(name) || name.includes(".golden.");
9326
9453
  }
9327
9454
  function classifyDevChange(path, roots = defaultDevWatchRoots()) {
9328
- const absolute = resolve4(path);
9329
- const root = roots.find((candidate) => isWithin(absolute, resolve4(candidate)));
9455
+ const absolute = resolve5(path);
9456
+ const root = roots.find((candidate) => isWithin(absolute, resolve5(candidate)));
9330
9457
  if (!root) return null;
9331
9458
  if (ignoredDevPath(absolute)) return null;
9332
9459
  const name = basename5(absolute);
9333
- const relToWorkspace = relative(resolve4(root), absolute);
9460
+ const relToWorkspace = relative(resolve5(root), absolute);
9334
9461
  const parts = relToWorkspace.split(sep2);
9335
9462
  const packageName = parts[0] === "packages" ? parts[1] : void 0;
9336
9463
  if (name === "package.json" && parts.length === 3 && packageName && CHILD_PACKAGE_METADATA.has(packageName)) {
@@ -9356,7 +9483,7 @@ function devConfigSyntaxError(path) {
9356
9483
  if (name !== "package.json" && !isTsconfig) return null;
9357
9484
  let text;
9358
9485
  try {
9359
- text = readFileSync7(path, "utf8");
9486
+ text = readFileSync8(path, "utf8");
9360
9487
  } catch (err) {
9361
9488
  return `${name}: ${err instanceof Error ? err.message : err}`;
9362
9489
  }
@@ -9452,7 +9579,7 @@ var Supervisor = class {
9452
9579
  watchSubscribe;
9453
9580
  reexec;
9454
9581
  supervisorLock;
9455
- statusPublisherToken = randomUUID4();
9582
+ statusPublisherToken = randomUUID5();
9456
9583
  processGeneration = currentProcessGeneration();
9457
9584
  ownerToken;
9458
9585
  launchTarget;
@@ -9471,10 +9598,10 @@ var Supervisor = class {
9471
9598
  if (launchOwner.pid !== callerGeneration.pid || launchOwner.processStart !== callerGeneration.processStart) throw new Error("dev supervisor caller is not the exact project launch owner");
9472
9599
  this.port = opts.port;
9473
9600
  this.launchTarget = opts.launchTarget;
9474
- this.cwd = resolve4(opts.cwd ?? opts.launchTarget.projectDir);
9601
+ this.cwd = resolve5(opts.cwd ?? opts.launchTarget.projectDir);
9475
9602
  if (this.cwd !== opts.launchTarget.projectDir) throw new Error("dev supervisor cwd does not match its owned project");
9476
9603
  this.parentEnv = projectLaunchEnvironment(opts.env ?? process.env, opts.launchTarget, opts.launchOwnerToken);
9477
- this.roots = (opts.watchRoots ?? defaultDevWatchRoots()).map((root) => resolve4(root));
9604
+ this.roots = (opts.watchRoots ?? defaultDevWatchRoots()).map((root) => resolve5(root));
9478
9605
  this.watchEnabled = opts.watch !== false;
9479
9606
  this.childEnvironment = opts.childEnvironment ?? (() => ({}));
9480
9607
  this.debounceMs = opts.debounceMs ?? DEV_RESTART_DEBOUNCE_MS;
@@ -9484,10 +9611,10 @@ var Supervisor = class {
9484
9611
  this.childArgs = opts.childArgs ?? [];
9485
9612
  this.watchSubscribe = opts.watchSubscribe ?? ((root, callback, options2) => watcher.subscribe(root, callback, options2));
9486
9613
  this.reexec = opts.reexec ?? (typeof process.execve === "function" ? (request) => process.execve(request.executable, request.argv, request.env) : void 0);
9487
- if (opts.stateDir && resolve4(opts.stateDir) !== opts.launchTarget.stateDir) {
9614
+ if (opts.stateDir && resolve5(opts.stateDir) !== opts.launchTarget.stateDir) {
9488
9615
  throw new Error("dev supervisor state directory does not match its owned project");
9489
9616
  }
9490
- this.supervisorLock = resolve4(opts.launchTarget.stateDir, "dev-supervisor.lock");
9617
+ this.supervisorLock = resolve5(opts.launchTarget.stateDir, "dev-supervisor.lock");
9491
9618
  this.ownerToken = opts.launchOwnerToken;
9492
9619
  this.logLine = opts.log ?? ((line) => log.info("supervisor", stripPrefix(line)));
9493
9620
  this.errorLine = opts.error ?? ((line) => log.error("supervisor", stripPrefix(line)));
@@ -9523,14 +9650,14 @@ var Supervisor = class {
9523
9650
  }
9524
9651
  async start() {
9525
9652
  if (this.supervisorLock) {
9526
- mkdirSync6(dirname4(this.supervisorLock), { recursive: true });
9653
+ mkdirSync7(dirname5(this.supervisorLock), { recursive: true });
9527
9654
  this.writeStatus("starting", "watcher initializing");
9528
9655
  }
9529
9656
  try {
9530
9657
  await this.publicProxy.listen();
9531
9658
  if (this.watchEnabled) {
9532
9659
  const settled = await Promise.allSettled(
9533
- this.roots.filter(existsSync3).map((root) => this.watchSubscribe(root, (err, events) => this.onWatch(err, events), {
9660
+ this.roots.filter(existsSync4).map((root) => this.watchSubscribe(root, (err, events) => this.onWatch(err, events), {
9534
9661
  ignore: DEV_WATCH_IGNORE
9535
9662
  }))
9536
9663
  );
@@ -9948,13 +10075,13 @@ async function startDevSupervisor(opts) {
9948
10075
  import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
9949
10076
  var PRODUCTION_REEXEC_FLAG = "--_frizz-production-reexec";
9950
10077
  function compareReleaseVersions(a, b) {
9951
- const parse = (value) => {
10078
+ const parse2 = (value) => {
9952
10079
  const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/u.exec(value);
9953
10080
  if (!match) return null;
9954
10081
  return { numeric: [Number(match[1]), Number(match[2]), Number(match[3])], prerelease: match[4] };
9955
10082
  };
9956
- const left = parse(a);
9957
- const right = parse(b);
10083
+ const left = parse2(a);
10084
+ const right = parse2(b);
9958
10085
  if (!left || !right) return null;
9959
10086
  for (let index = 0; index < left.numeric.length; index++) {
9960
10087
  const delta = left.numeric[index] - right.numeric[index];
@@ -10019,7 +10146,7 @@ var npmRegistryReleaseAdapter = {
10019
10146
  import { spawnSync } from "node:child_process";
10020
10147
  import { chmodSync, statSync as statSync5 } from "node:fs";
10021
10148
  import { createRequire as createRequire2 } from "node:module";
10022
- import { dirname as dirname5, join as join9 } from "node:path";
10149
+ import { dirname as dirname6, join as join10 } from "node:path";
10023
10150
  var SUPPORTED_NODE_LINES = [
10024
10151
  { major: 22, minor: 13 },
10025
10152
  { major: 23, minor: 4 }
@@ -10037,9 +10164,7 @@ function nodeVersionIsSupported(major, minor) {
10037
10164
  if (line) return minor >= line.minor;
10038
10165
  return major > SUPPORTED_NODE_LINES[SUPPORTED_NODE_LINES.length - 1].major;
10039
10166
  }
10040
- var REQUIRED_EXECUTABLES = [
10041
- { name: "git", need: "Frizz identifies a project by its Git repository" }
10042
- ];
10167
+ var REQUIRED_EXECUTABLES = [];
10043
10168
  function assertRequiredExecutables(command = commandIsAvailable) {
10044
10169
  for (const { name, need } of REQUIRED_EXECUTABLES) {
10045
10170
  if (command(name)) continue;
@@ -10072,8 +10197,8 @@ function ensureNativeHelperPermissions(options2 = {}) {
10072
10197
  const chmod = options2.chmod ?? ((path, mode) => chmodSync(path, mode));
10073
10198
  const resolvePty = options2.resolvePty ?? (() => createRequire2(import.meta.url).resolve("node-pty/package.json"));
10074
10199
  try {
10075
- const helper = join9(
10076
- dirname5(resolvePty()),
10200
+ const helper = join10(
10201
+ dirname6(resolvePty()),
10077
10202
  "prebuilds",
10078
10203
  `${platform}-${options2.arch ?? process.arch}`,
10079
10204
  "spawn-helper"
@@ -10089,7 +10214,7 @@ function ensureNativeHelperPermissions(options2 = {}) {
10089
10214
  var PACKAGE_NAME = process.env.FRIZZ_REGISTRY_PACKAGE ?? "frizz";
10090
10215
  function resolvePackageVersion() {
10091
10216
  try {
10092
- const manifest = JSON.parse(readFileSync8(join10(import.meta.dirname, "..", "package.json"), "utf8"));
10217
+ const manifest = JSON.parse(readFileSync9(join11(import.meta.dirname, "..", "package.json"), "utf8"));
10093
10218
  if (typeof manifest.version === "string" && manifest.version.trim()) return manifest.version.trim();
10094
10219
  } catch {
10095
10220
  }
@@ -10197,7 +10322,7 @@ async function openOrPrint(port, reused) {
10197
10322
  readout?.begin("browser", options.appMode ? "requesting app window" : "requesting default browser");
10198
10323
  try {
10199
10324
  if (options.appMode) {
10200
- await launchApp(url, { dataPath: join10(workspace.stateDir, "browser-profile") });
10325
+ await launchApp(url, { dataPath: join11(workspace.stateDir, "browser-profile") });
10201
10326
  browser = reused ? "focused the Frizz app window" : "opened the Frizz app window";
10202
10327
  } else {
10203
10328
  await launchBrowserTab(url);
@@ -10226,7 +10351,7 @@ async function openOrPrint(port, reused) {
10226
10351
  for (const warning of warnings) console.log(warning);
10227
10352
  return;
10228
10353
  }
10229
- const home = homedir7();
10354
+ const home = homedir8();
10230
10355
  readout.ready(
10231
10356
  [
10232
10357
  { label: "Local", value: `${url}/`, accent: true },
@@ -10259,10 +10384,10 @@ async function runSupervisor(port, token) {
10259
10384
  target,
10260
10385
  owner.token
10261
10386
  );
10262
- const webDist = join10(import.meta.dirname, "..", "web-dist");
10263
- const runtimeDir = join10(import.meta.dirname, "..", "runtime");
10264
- const scriptsDir = join10(runtimeDir, "board");
10265
- const workerPluginDir = join10(runtimeDir, "cc-worker");
10387
+ const webDist = join11(import.meta.dirname, "..", "web-dist");
10388
+ const runtimeDir = join11(import.meta.dirname, "..", "runtime");
10389
+ const scriptsDir = join11(runtimeDir, "board");
10390
+ const workerPluginDir = join11(runtimeDir, "cc-worker");
10266
10391
  const childEntry = fileURLToPath2(new URL("./dev-child.js", import.meta.url));
10267
10392
  let plannedUpdate;
10268
10393
  let updateAvailable = true;
@@ -10316,7 +10441,7 @@ async function runSupervisor(port, token) {
10316
10441
  exit: (code) => {
10317
10442
  logger.info("launcher", `stopped with code ${code}`);
10318
10443
  const suffix = logger.file ? `
10319
- log: ${tildePath(logger.file, homedir7())}` : "";
10444
+ log: ${tildePath(logger.file, homedir8())}` : "";
10320
10445
  process.stdout.write(
10321
10446
  code === 0 ? `
10322
10447
  Frizz stopped. Agent sessions in tmux keep running.${suffix}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frizz",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "description": "A local web UI for running many coding agents at once",
6
6
  "keywords": [