rudel 0.1.9 → 0.1.10

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.
Files changed (2) hide show
  1. package/dist/cli.js +278 -223
  2. package/package.json +3 -2
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
3
  var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
@@ -26,7 +26,7 @@ var __export = (target, all) => {
26
26
  set: (newValue) => all[name] = () => newValue
27
27
  });
28
28
  };
29
- var __require = import.meta.require;
29
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
30
 
31
31
  // ../../node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
32
32
  var require_picocolors = __commonJS((exports, module) => {
@@ -1959,7 +1959,7 @@ async function run(app, inputs, context) {
1959
1959
  // package.json
1960
1960
  var package_default = {
1961
1961
  name: "rudel",
1962
- version: "0.1.9",
1962
+ version: "0.1.10",
1963
1963
  type: "module",
1964
1964
  description: "CLI for the Coding Agent Analytics Platform rudel.ai",
1965
1965
  license: "MIT",
@@ -1991,7 +1991,7 @@ var package_default = {
1991
1991
  scripts: {
1992
1992
  dev: "bun run src/bin/cli.ts",
1993
1993
  "check-types": "tsc --noEmit",
1994
- build: "bun build src/bin/cli.ts --outdir dist --target bun",
1994
+ build: "bun build src/bin/cli.ts --outdir dist --target node",
1995
1995
  test: "bun test"
1996
1996
  },
1997
1997
  dependencies: {
@@ -2007,15 +2007,16 @@ var package_default = {
2007
2007
  "@rudel/agent-adapters": "workspace:*",
2008
2008
  "@rudel/api-routes": "workspace:*",
2009
2009
  "@rudel/typescript-config": "workspace:*",
2010
+ "@types/node": "^22",
2010
2011
  "bun-types": "latest",
2011
2012
  typescript: "5.9.2"
2012
2013
  }
2013
2014
  };
2014
2015
 
2015
2016
  // ../../packages/agent-adapters/src/adapters/claude-code/index.ts
2016
- import { readdir as readdir2, readFile as readFile2, stat } from "fs/promises";
2017
- import { homedir as homedir2 } from "os";
2018
- import { dirname as dirname2, join as join3 } from "path";
2017
+ import { readdir as readdir2, readFile as readFile2, stat } from "node:fs/promises";
2018
+ import { homedir as homedir2 } from "node:os";
2019
+ import { dirname as dirname2, join as join3 } from "node:path";
2019
2020
 
2020
2021
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
2021
2022
  var exports_external = {};
@@ -6076,9 +6077,9 @@ async function ingestRudelCodexSessions(ingestor, rows, options) {
6076
6077
  await ingestor.insert({ table: "rudel.codex_sessions", values: data });
6077
6078
  }
6078
6079
  // ../../packages/agent-adapters/src/utils.ts
6079
- import { readdir, readFile } from "fs/promises";
6080
- import { homedir } from "os";
6081
- import { join } from "path";
6080
+ import { readdir, readFile } from "node:fs/promises";
6081
+ import { homedir } from "node:os";
6082
+ import { join } from "node:path";
6082
6083
  function toClickHouseDateTime(isoString) {
6083
6084
  return isoString.replace("T", " ").replace("Z", "").replace(/\+.*$/, "");
6084
6085
  }
@@ -6134,9 +6135,9 @@ function toDisplayPath(absolutePath) {
6134
6135
  }
6135
6136
 
6136
6137
  // ../../packages/agent-adapters/src/adapters/claude-code/settings.ts
6137
- import { execSync } from "child_process";
6138
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
6139
- import { dirname, join as join2, resolve } from "path";
6138
+ import { execSync } from "node:child_process";
6139
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6140
+ import { dirname, join as join2, resolve } from "node:path";
6140
6141
  var HOOK_COMMAND = "rudel hooks claude session-end";
6141
6142
  function findClaudeDir() {
6142
6143
  let dir = resolve(process.cwd());
@@ -6455,14 +6456,14 @@ class ClaudeCodeAdapter {
6455
6456
  }
6456
6457
  var claudeCodeAdapter = new ClaudeCodeAdapter;
6457
6458
  // ../../packages/agent-adapters/src/adapters/codex/index.ts
6458
- import { readFile as readFile3 } from "fs/promises";
6459
- import { homedir as homedir4 } from "os";
6460
- import { join as join5 } from "path";
6459
+ import { readFile as readFile3 } from "node:fs/promises";
6460
+ import { homedir as homedir4 } from "node:os";
6461
+ import { join as join5 } from "node:path";
6461
6462
 
6462
6463
  // ../../packages/agent-adapters/src/adapters/codex/config.ts
6463
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6464
- import { homedir as homedir3 } from "os";
6465
- import { join as join4 } from "path";
6464
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
6465
+ import { homedir as homedir3 } from "node:os";
6466
+ import { join as join4 } from "node:path";
6466
6467
 
6467
6468
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
6468
6469
  /*!
@@ -6584,7 +6585,7 @@ function skipComment(str, ptr) {
6584
6585
  if (c === "\r" && str[i + 1] === `
6585
6586
  `)
6586
6587
  return i + 1;
6587
- if (c < " " && c !== "\t" || c === "\x7F") {
6588
+ if (c < " " && c !== "\t" || c === "") {
6588
6589
  throw new TomlError("control characters are not allowed in comments", {
6589
6590
  toml: str,
6590
6591
  ptr
@@ -6831,7 +6832,7 @@ function parseString(str, ptr = 0, endPtr = str.length) {
6831
6832
  ptr: ptr - 1
6832
6833
  });
6833
6834
  }
6834
- } else if (c < " " && c !== "\t" || c === "\x7F") {
6835
+ } else if (c < " " && c !== "\t" || c === "") {
6835
6836
  throw new TomlError("control characters are not allowed in strings", {
6836
6837
  toml: str,
6837
6838
  ptr: ptr - 1
@@ -7746,7 +7747,7 @@ class CodexAdapter {
7746
7747
  }
7747
7748
  var codexAdapter = new CodexAdapter;
7748
7749
  // ../../packages/agent-adapters/src/registry.ts
7749
- import { existsSync as existsSync3 } from "fs";
7750
+ import { existsSync as existsSync3 } from "node:fs";
7750
7751
  var adapters = new Map;
7751
7752
  function registerAdapter(adapter) {
7752
7753
  adapters.set(adapter.source, adapter);
@@ -7769,11 +7770,27 @@ registerAdapter(claudeCodeAdapter);
7769
7770
  registerAdapter(codexAdapter);
7770
7771
 
7771
7772
  // src/lib/project-grouping.ts
7772
- import { homedir as homedir6 } from "os";
7773
+ import { homedir as homedir6 } from "node:os";
7774
+
7775
+ // src/lib/git-info.ts
7776
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
7777
+ import { join as join6 } from "node:path";
7778
+
7779
+ // src/lib/exec.ts
7780
+ import { execFile } from "node:child_process";
7781
+ function exec(cmd, args) {
7782
+ return new Promise((resolve2) => {
7783
+ execFile(cmd, args, { encoding: "utf8" }, (error, stdout, stderr) => {
7784
+ resolve2({
7785
+ exitCode: error ? error.code ?? 1 : 0,
7786
+ stdout,
7787
+ stderr
7788
+ });
7789
+ });
7790
+ });
7791
+ }
7773
7792
 
7774
7793
  // src/lib/git-info.ts
7775
- import { join as join6 } from "path";
7776
- var {$ } = globalThis.Bun;
7777
7794
  function normalizeRemoteUrl(url) {
7778
7795
  return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7779
7796
  }
@@ -7795,54 +7812,59 @@ async function getGitInfo(cwd) {
7795
7812
  }
7796
7813
  async function getPackageInfo(cwd) {
7797
7814
  try {
7798
- const gitRootResult = await $`git -C ${cwd} rev-parse --show-toplevel`.quiet();
7799
- const root = gitRootResult.exitCode === 0 ? gitRootResult.text().trim() : cwd;
7800
- return await getNodePackage(root) ?? await getPythonPackage(root) ?? await getRustPackage(root) ?? await getGoModule(root);
7815
+ const result = await exec("git", [
7816
+ "-C",
7817
+ cwd,
7818
+ "rev-parse",
7819
+ "--show-toplevel"
7820
+ ]);
7821
+ const root = result.exitCode === 0 ? result.stdout.trim() : cwd;
7822
+ return getNodePackage(root) ?? getPythonPackage(root) ?? getRustPackage(root) ?? getGoModule(root);
7801
7823
  } catch {
7802
7824
  return null;
7803
7825
  }
7804
7826
  }
7805
- async function getNodePackage(root) {
7827
+ function getNodePackage(root) {
7806
7828
  try {
7807
- const file = Bun.file(join6(root, "package.json"));
7808
- if (!await file.exists())
7829
+ const filePath = join6(root, "package.json");
7830
+ if (!existsSync4(filePath))
7809
7831
  return null;
7810
- const pkg = await file.json();
7832
+ const pkg = JSON.parse(readFileSync3(filePath, "utf-8"));
7811
7833
  return pkg.name ? { name: pkg.name, type: "package.json" } : null;
7812
7834
  } catch {
7813
7835
  return null;
7814
7836
  }
7815
7837
  }
7816
- async function getPythonPackage(root) {
7838
+ function getPythonPackage(root) {
7817
7839
  try {
7818
- const file = Bun.file(join6(root, "pyproject.toml"));
7819
- if (!await file.exists())
7840
+ const filePath = join6(root, "pyproject.toml");
7841
+ if (!existsSync4(filePath))
7820
7842
  return null;
7821
- const content = await file.text();
7843
+ const content = readFileSync3(filePath, "utf-8");
7822
7844
  const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
7823
7845
  return name ? { name, type: "pyproject.toml" } : null;
7824
7846
  } catch {
7825
7847
  return null;
7826
7848
  }
7827
7849
  }
7828
- async function getRustPackage(root) {
7850
+ function getRustPackage(root) {
7829
7851
  try {
7830
- const file = Bun.file(join6(root, "Cargo.toml"));
7831
- if (!await file.exists())
7852
+ const filePath = join6(root, "Cargo.toml");
7853
+ if (!existsSync4(filePath))
7832
7854
  return null;
7833
- const content = await file.text();
7855
+ const content = readFileSync3(filePath, "utf-8");
7834
7856
  const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
7835
7857
  return name ? { name, type: "Cargo.toml" } : null;
7836
7858
  } catch {
7837
7859
  return null;
7838
7860
  }
7839
7861
  }
7840
- async function getGoModule(root) {
7862
+ function getGoModule(root) {
7841
7863
  try {
7842
- const file = Bun.file(join6(root, "go.mod"));
7843
- if (!await file.exists())
7864
+ const filePath = join6(root, "go.mod");
7865
+ if (!existsSync4(filePath))
7844
7866
  return null;
7845
- const content = await file.text();
7867
+ const content = readFileSync3(filePath, "utf-8");
7846
7868
  const name = content.match(/^module\s+(\S+)/m)?.[1];
7847
7869
  return name ? { name, type: "go.mod" } : null;
7848
7870
  } catch {
@@ -7851,45 +7873,58 @@ async function getGoModule(root) {
7851
7873
  }
7852
7874
  async function getGitRemoteUrl(cwd) {
7853
7875
  try {
7854
- const result = await $`git -C ${cwd} remote get-url origin`.quiet();
7876
+ const result = await exec("git", [
7877
+ "-C",
7878
+ cwd,
7879
+ "remote",
7880
+ "get-url",
7881
+ "origin"
7882
+ ]);
7855
7883
  if (result.exitCode !== 0)
7856
7884
  return null;
7857
- return result.text().trim() || null;
7885
+ return result.stdout.trim() || null;
7858
7886
  } catch {
7859
7887
  return null;
7860
7888
  }
7861
7889
  }
7862
7890
  async function getGitBranch(cwd) {
7863
7891
  try {
7864
- const result = await $`git -C ${cwd} rev-parse --abbrev-ref HEAD`.quiet();
7892
+ const result = await exec("git", [
7893
+ "-C",
7894
+ cwd,
7895
+ "rev-parse",
7896
+ "--abbrev-ref",
7897
+ "HEAD"
7898
+ ]);
7865
7899
  if (result.exitCode !== 0)
7866
7900
  return null;
7867
- return result.text().trim();
7901
+ return result.stdout.trim();
7868
7902
  } catch {
7869
7903
  return null;
7870
7904
  }
7871
7905
  }
7872
7906
  async function getGitSha(cwd) {
7873
7907
  try {
7874
- const result = await $`git -C ${cwd} rev-parse HEAD`.quiet();
7908
+ const result = await exec("git", ["-C", cwd, "rev-parse", "HEAD"]);
7875
7909
  if (result.exitCode !== 0)
7876
7910
  return null;
7877
- return result.text().trim();
7911
+ return result.stdout.trim();
7878
7912
  } catch {
7879
7913
  return null;
7880
7914
  }
7881
7915
  }
7882
7916
 
7883
7917
  // src/lib/remote-cache.ts
7884
- import { homedir as homedir5 } from "os";
7885
- import { join as join7 } from "path";
7918
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
7919
+ import { mkdir, writeFile } from "node:fs/promises";
7920
+ import { homedir as homedir5 } from "node:os";
7921
+ import { dirname as dirname3, join as join7 } from "node:path";
7886
7922
  var CACHE_PATH = join7(homedir5(), ".rudel", "remote-cache.json");
7887
7923
  async function getRemoteCache() {
7888
7924
  try {
7889
- const file = Bun.file(CACHE_PATH);
7890
- if (!await file.exists())
7925
+ if (!existsSync5(CACHE_PATH))
7891
7926
  return {};
7892
- return await file.json();
7927
+ return JSON.parse(readFileSync4(CACHE_PATH, "utf-8"));
7893
7928
  } catch {
7894
7929
  return {};
7895
7930
  }
@@ -7902,10 +7937,8 @@ function cacheRemote(cache, encodedDir, normalizedRemote) {
7902
7937
  }
7903
7938
  async function cacheRemotes(cache) {
7904
7939
  try {
7905
- const { mkdir } = await import("fs/promises");
7906
- const { dirname: dirname3 } = await import("path");
7907
7940
  await mkdir(dirname3(CACHE_PATH), { recursive: true });
7908
- await Bun.write(CACHE_PATH, JSON.stringify(cache));
7941
+ await writeFile(CACHE_PATH, JSON.stringify(cache));
7909
7942
  } catch {}
7910
7943
  }
7911
7944
 
@@ -8105,10 +8138,10 @@ var devRouteMap = buildRouteMap({
8105
8138
  // ../../node_modules/.bun/@clack+core@1.0.1/node_modules/@clack/core/dist/index.mjs
8106
8139
  var import_picocolors = __toESM(require_picocolors(), 1);
8107
8140
  var import_sisteransi = __toESM(require_src(), 1);
8108
- import { stdout as R, stdin as q } from "process";
8109
- import * as k from "readline";
8110
- import ot from "readline";
8111
- import { ReadStream as J } from "tty";
8141
+ import { stdout as R, stdin as q } from "node:process";
8142
+ import * as k from "node:readline";
8143
+ import ot from "node:readline";
8144
+ import { ReadStream as J } from "node:tty";
8112
8145
  function B(t, e, s) {
8113
8146
  if (!s.some((u) => !u.disabled))
8114
8147
  return t;
@@ -8134,8 +8167,8 @@ var X = (t, e = {}, s = {}) => {
8134
8167
  const ut = t.slice(C, w) || t.slice(h, o);
8135
8168
  v = 0;
8136
8169
  for (const Y of ut.replaceAll(ct, "")) {
8137
- const $2 = Y.codePointAt(0) || 0;
8138
- if (lt($2) ? f = m : ht($2) ? f = V : E !== A && at($2) ? f = E : f = A, c + f > b && (d = Math.min(d, Math.max(C, h) + v)), c + f > i) {
8170
+ const $ = Y.codePointAt(0) || 0;
8171
+ if (lt($) ? f = m : ht($) ? f = V : E !== A && at($) ? f = E : f = A, c + f > b && (d = Math.min(d, Math.max(C, h) + v)), c + f > i) {
8139
8172
  F = true;
8140
8173
  break t;
8141
8174
  }
@@ -8192,7 +8225,7 @@ var X = (t, e = {}, s = {}) => {
8192
8225
  var pt = { limit: 1 / 0, ellipsis: "", ellipsisWidth: 0 };
8193
8226
  var S = (t, e = {}) => X(t, pt, e).width;
8194
8227
  var W = "\x1B";
8195
- var Z = "\x9B";
8228
+ var Z = "›";
8196
8229
  var Ft = 39;
8197
8230
  var j = "\x07";
8198
8231
  var Q = "[";
@@ -8513,7 +8546,7 @@ class Vt extends x {
8513
8546
  if (!this.userInput)
8514
8547
  return import_picocolors.default.inverse(import_picocolors.default.hidden("_"));
8515
8548
  if (this._cursor >= this.userInput.length)
8516
- return `${this.userInput}\u2588`;
8549
+ return `${this.userInput}█`;
8517
8550
  const e = this.userInput.slice(0, this._cursor), [s, ...i] = this.userInput.slice(this._cursor);
8518
8551
  return `${e}${import_picocolors.default.inverse(s)}${i.join("")}`;
8519
8552
  }
@@ -8701,7 +8734,7 @@ class Wt extends x {
8701
8734
 
8702
8735
  // ../../node_modules/.bun/@clack+prompts@1.0.1/node_modules/@clack/prompts/dist/index.mjs
8703
8736
  var import_picocolors2 = __toESM(require_picocolors(), 1);
8704
- import N2 from "process";
8737
+ import N2 from "node:process";
8705
8738
  var import_sisteransi2 = __toESM(require_src(), 1);
8706
8739
  function me() {
8707
8740
  return N2.platform !== "win32" ? N2.env.TERM !== "linux" : !!N2.env.CI || !!N2.env.WT_SESSION || !!N2.env.TERMINUS_SUBLIME || N2.env.ConEmuTask === "{cmd::Cmder}" || N2.env.TERM_PROGRAM === "Terminus-Sublime" || N2.env.TERM_PROGRAM === "vscode" || N2.env.TERM === "xterm-256color" || N2.env.TERM === "alacritty" || N2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
@@ -8709,31 +8742,31 @@ function me() {
8709
8742
  var et2 = me();
8710
8743
  var ct2 = () => process.env.CI === "true";
8711
8744
  var C = (t, r) => et2 ? t : r;
8712
- var Rt = C("\u25C6", "*");
8713
- var dt2 = C("\u25A0", "x");
8714
- var $t2 = C("\u25B2", "x");
8715
- var V = C("\u25C7", "o");
8716
- var ht2 = C("\u250C", "T");
8717
- var d = C("\u2502", "|");
8718
- var x2 = C("\u2514", "\u2014");
8719
- var Ot = C("\u2510", "T");
8720
- var Pt = C("\u2518", "\u2014");
8721
- var Q2 = C("\u25CF", ">");
8722
- var H2 = C("\u25CB", " ");
8723
- var st2 = C("\u25FB", "[\u2022]");
8724
- var U2 = C("\u25FC", "[+]");
8725
- var q2 = C("\u25FB", "[ ]");
8726
- var Nt = C("\u25AA", "\u2022");
8727
- var rt2 = C("\u2500", "-");
8728
- var mt2 = C("\u256E", "+");
8729
- var Wt2 = C("\u251C", "+");
8730
- var pt2 = C("\u256F", "+");
8731
- var gt2 = C("\u2570", "+");
8732
- var Lt2 = C("\u256D", "+");
8733
- var ft2 = C("\u25CF", "\u2022");
8734
- var Ft2 = C("\u25C6", "*");
8735
- var yt2 = C("\u25B2", "!");
8736
- var Et2 = C("\u25A0", "x");
8745
+ var Rt = C("", "*");
8746
+ var dt2 = C("", "x");
8747
+ var $t2 = C("", "x");
8748
+ var V = C("", "o");
8749
+ var ht2 = C("", "T");
8750
+ var d = C("", "|");
8751
+ var x2 = C("", "");
8752
+ var Ot = C("", "T");
8753
+ var Pt = C("", "");
8754
+ var Q2 = C("", ">");
8755
+ var H2 = C("", " ");
8756
+ var st2 = C("", "[]");
8757
+ var U2 = C("", "[+]");
8758
+ var q2 = C("", "[ ]");
8759
+ var Nt = C("", "");
8760
+ var rt2 = C("", "-");
8761
+ var mt2 = C("", "+");
8762
+ var Wt2 = C("", "+");
8763
+ var pt2 = C("", "+");
8764
+ var gt2 = C("", "+");
8765
+ var Lt2 = C("", "+");
8766
+ var ft2 = C("", "");
8767
+ var Ft2 = C("", "*");
8768
+ var yt2 = C("", "!");
8769
+ var Et2 = C("", "x");
8737
8770
  var W2 = (t) => {
8738
8771
  switch (t) {
8739
8772
  case "initial":
@@ -8772,15 +8805,15 @@ var Fe = /\p{M}+/gu;
8772
8805
  var ye = { limit: 1 / 0, ellipsis: "" };
8773
8806
  var jt = (t, r = {}, s = {}) => {
8774
8807
  const i = r.limit ?? 1 / 0, a = r.ellipsis ?? "", o = r?.ellipsisWidth ?? (a ? jt(a, ye, s).width : 0), u = s.ansiWidth ?? 0, l = s.controlWidth ?? 0, n = s.tabWidth ?? 8, c = s.ambiguousWidth ?? 1, g = s.emojiWidth ?? 2, F = s.fullWidthWidth ?? 2, p = s.regularWidth ?? 1, E = s.wideWidth ?? 2;
8775
- let $2 = 0, m = 0, h = t.length, y2 = 0, f = false, v = h, S2 = Math.max(0, i - o), I2 = 0, B2 = 0, A = 0, w = 0;
8808
+ let $ = 0, m = 0, h = t.length, y2 = 0, f = false, v = h, S2 = Math.max(0, i - o), I2 = 0, B2 = 0, A = 0, w = 0;
8776
8809
  t:
8777
8810
  for (;; ) {
8778
- if (B2 > I2 || m >= h && m > $2) {
8779
- const _2 = t.slice(I2, B2) || t.slice($2, m);
8811
+ if (B2 > I2 || m >= h && m > $) {
8812
+ const _2 = t.slice(I2, B2) || t.slice($, m);
8780
8813
  y2 = 0;
8781
8814
  for (const D2 of _2.replaceAll(Fe, "")) {
8782
8815
  const T2 = D2.codePointAt(0) || 0;
8783
- if (ge(T2) ? w = F : fe(T2) ? w = E : c !== p && pe(T2) ? w = c : w = p, A + w > S2 && (v = Math.min(v, Math.max(I2, $2) + y2)), A + w > i) {
8816
+ if (ge(T2) ? w = F : fe(T2) ? w = E : c !== p && pe(T2) ? w = c : w = p, A + w > S2 && (v = Math.min(v, Math.max(I2, $) + y2)), A + w > i) {
8784
8817
  f = true;
8785
8818
  break t;
8786
8819
  }
@@ -8795,7 +8828,7 @@ var jt = (t, r = {}, s = {}) => {
8795
8828
  f = true;
8796
8829
  break;
8797
8830
  }
8798
- A += w, I2 = $2, B2 = m, m = $2 = at2.lastIndex;
8831
+ A += w, I2 = $, B2 = m, m = $ = at2.lastIndex;
8799
8832
  continue;
8800
8833
  }
8801
8834
  if (At2.lastIndex = m, At2.test(t)) {
@@ -8803,7 +8836,7 @@ var jt = (t, r = {}, s = {}) => {
8803
8836
  f = true;
8804
8837
  break;
8805
8838
  }
8806
- A += u, I2 = $2, B2 = m, m = $2 = At2.lastIndex;
8839
+ A += u, I2 = $, B2 = m, m = $ = At2.lastIndex;
8807
8840
  continue;
8808
8841
  }
8809
8842
  if (it2.lastIndex = m, it2.test(t)) {
@@ -8811,7 +8844,7 @@ var jt = (t, r = {}, s = {}) => {
8811
8844
  f = true;
8812
8845
  break;
8813
8846
  }
8814
- A += w, I2 = $2, B2 = m, m = $2 = it2.lastIndex;
8847
+ A += w, I2 = $, B2 = m, m = $ = it2.lastIndex;
8815
8848
  continue;
8816
8849
  }
8817
8850
  if (nt2.lastIndex = m, nt2.test(t)) {
@@ -8819,7 +8852,7 @@ var jt = (t, r = {}, s = {}) => {
8819
8852
  f = true;
8820
8853
  break;
8821
8854
  }
8822
- A += w, I2 = $2, B2 = m, m = $2 = nt2.lastIndex;
8855
+ A += w, I2 = $, B2 = m, m = $ = nt2.lastIndex;
8823
8856
  continue;
8824
8857
  }
8825
8858
  if (wt2.lastIndex = m, wt2.test(t)) {
@@ -8827,7 +8860,7 @@ var jt = (t, r = {}, s = {}) => {
8827
8860
  f = true;
8828
8861
  break;
8829
8862
  }
8830
- A += g, I2 = $2, B2 = m, m = $2 = wt2.lastIndex;
8863
+ A += g, I2 = $, B2 = m, m = $ = wt2.lastIndex;
8831
8864
  continue;
8832
8865
  }
8833
8866
  m += 1;
@@ -8837,7 +8870,7 @@ var jt = (t, r = {}, s = {}) => {
8837
8870
  var Ee = { limit: 1 / 0, ellipsis: "", ellipsisWidth: 0 };
8838
8871
  var M2 = (t, r = {}) => jt(t, Ee, r).width;
8839
8872
  var ot2 = "\x1B";
8840
- var Gt = "\x9B";
8873
+ var Gt = "›";
8841
8874
  var ve = 39;
8842
8875
  var Ct2 = "\x07";
8843
8876
  var kt2 = "[";
@@ -8890,34 +8923,34 @@ var Ie = (t, r, s = {}) => {
8890
8923
  let i = "", a, o;
8891
8924
  const u = t.split(" "), l = Ce(u);
8892
8925
  let n = [""];
8893
- for (const [$2, m] of u.entries()) {
8926
+ for (const [$, m] of u.entries()) {
8894
8927
  s.trim !== false && (n[n.length - 1] = (n.at(-1) ?? "").trimStart());
8895
8928
  let h = M2(n.at(-1) ?? "");
8896
- if ($2 !== 0 && (h >= r && (s.wordWrap === false || s.trim === false) && (n.push(""), h = 0), (h > 0 || s.trim === false) && (n[n.length - 1] += " ", h++)), s.hard && l[$2] > r) {
8897
- const y2 = r - h, f = 1 + Math.floor((l[$2] - y2 - 1) / r);
8898
- Math.floor((l[$2] - 1) / r) < f && n.push(""), It2(n, m, r);
8929
+ if ($ !== 0 && (h >= r && (s.wordWrap === false || s.trim === false) && (n.push(""), h = 0), (h > 0 || s.trim === false) && (n[n.length - 1] += " ", h++)), s.hard && l[$] > r) {
8930
+ const y2 = r - h, f = 1 + Math.floor((l[$] - y2 - 1) / r);
8931
+ Math.floor((l[$] - 1) / r) < f && n.push(""), It2(n, m, r);
8899
8932
  continue;
8900
8933
  }
8901
- if (h + l[$2] > r && h > 0 && l[$2] > 0) {
8934
+ if (h + l[$] > r && h > 0 && l[$] > 0) {
8902
8935
  if (s.wordWrap === false && h < r) {
8903
8936
  It2(n, m, r);
8904
8937
  continue;
8905
8938
  }
8906
8939
  n.push("");
8907
8940
  }
8908
- if (h + l[$2] > r && s.wordWrap === false) {
8941
+ if (h + l[$] > r && s.wordWrap === false) {
8909
8942
  It2(n, m, r);
8910
8943
  continue;
8911
8944
  }
8912
8945
  n[n.length - 1] += m;
8913
8946
  }
8914
- s.trim !== false && (n = n.map(($2) => Se($2)));
8947
+ s.trim !== false && (n = n.map(($) => Se($)));
8915
8948
  const c = n.join(`
8916
8949
  `), g = c[Symbol.iterator]();
8917
8950
  let F = g.next(), p = g.next(), E = 0;
8918
8951
  for (;!F.done; ) {
8919
- const $2 = F.value, m = p.value;
8920
- if (i += $2, $2 === ot2 || $2 === Gt) {
8952
+ const $ = F.value, m = p.value;
8953
+ if (i += $, $ === ot2 || $ === Gt) {
8921
8954
  Ht.lastIndex = E + 1;
8922
8955
  const f = Ht.exec(c)?.groups;
8923
8956
  if (f?.code !== undefined) {
@@ -8928,8 +8961,8 @@ var Ie = (t, r, s = {}) => {
8928
8961
  }
8929
8962
  const h = a ? we(a) : undefined;
8930
8963
  m === `
8931
- ` ? (o && (i += Kt("")), a && h && (i += Ut(h))) : $2 === `
8932
- ` && (a && h && (i += Ut(a)), o && (i += Kt(o))), E += $2.length, F = p, p = g.next();
8964
+ ` ? (o && (i += Kt("")), a && h && (i += Ut(h))) : $ === `
8965
+ ` && (a && h && (i += Ut(a)), o && (i += Kt(o))), E += $.length, F = p, p = g.next();
8933
8966
  }
8934
8967
  return i;
8935
8968
  };
@@ -8951,13 +8984,13 @@ var be = (t, r, s, i, a) => {
8951
8984
  };
8952
8985
  var X2 = (t) => {
8953
8986
  const { cursor: r, options: s, style: i } = t, a = t.output ?? process.stdout, o = rt(a), u = t.columnPadding ?? 0, l = t.rowPadding ?? 4, n = o - u, c = nt(a), g = import_picocolors2.default.dim("..."), F = t.maxItems ?? Number.POSITIVE_INFINITY, p = Math.max(c - l, 0), E = Math.max(Math.min(F, p), 5);
8954
- let $2 = 0;
8955
- r >= E - 3 && ($2 = Math.max(Math.min(r - E + 3, s.length - E), 0));
8956
- let m = E < s.length && $2 > 0, h = E < s.length && $2 + E < s.length;
8957
- const y2 = Math.min($2 + E, s.length), f = [];
8987
+ let $ = 0;
8988
+ r >= E - 3 && ($ = Math.max(Math.min(r - E + 3, s.length - E), 0));
8989
+ let m = E < s.length && $ > 0, h = E < s.length && $ + E < s.length;
8990
+ const y2 = Math.min($ + E, s.length), f = [];
8958
8991
  let v = 0;
8959
8992
  m && v++, h && v++;
8960
- const S2 = $2 + (m ? 1 : 0), I2 = y2 - (h ? 1 : 0);
8993
+ const S2 = $ + (m ? 1 : 0), I2 = y2 - (h ? 1 : 0);
8961
8994
  for (let A = S2;A < I2; A++) {
8962
8995
  const w = J2(i(s[A], A === r), n, { hard: true, trim: false }).split(`
8963
8996
  `);
@@ -8983,8 +9016,8 @@ function Yt(t, r, s, i) {
8983
9016
  }
8984
9017
  var Te = (t) => t;
8985
9018
  var Me = (t = "", r = "", s) => {
8986
- const i = s?.output ?? process.stdout, a = rt(i), o = 2, u = s?.titlePadding ?? 1, l = s?.contentPadding ?? 2, n = s?.width === undefined || s.width === "auto" ? 1 : Math.min(1, s.width), c = s?.withGuide ?? _.withGuide ? `${d} ` : "", g = s?.formatBorder ?? Te, F = ((s?.rounded) ? _e : De).map(g), p = g(rt2), E = g(d), $2 = M2(c), m = M2(r), h = a - $2;
8987
- let y2 = Math.floor(a * n) - $2;
9019
+ const i = s?.output ?? process.stdout, a = rt(i), o = 2, u = s?.titlePadding ?? 1, l = s?.contentPadding ?? 2, n = s?.width === undefined || s.width === "auto" ? 1 : Math.min(1, s.width), c = s?.withGuide ?? _.withGuide ? `${d} ` : "", g = s?.formatBorder ?? Te, F = ((s?.rounded) ? _e : De).map(g), p = g(rt2), E = g(d), $ = M2(c), m = M2(r), h = a - $;
9020
+ let y2 = Math.floor(a * n) - $;
8988
9021
  if (s?.width === "auto") {
8989
9022
  const _2 = t.split(`
8990
9023
  `);
@@ -9046,8 +9079,8 @@ var R2 = { message: (t = [], { symbol: r = import_picocolors2.default.gray(d), s
9046
9079
  if (F.length > 0) {
9047
9080
  const [p, ...E] = F;
9048
9081
  p.length > 0 ? u.push(`${c}${p}`) : u.push(l ? r : "");
9049
- for (const $2 of E)
9050
- $2.length > 0 ? u.push(`${g}${$2}`) : u.push(l ? s : "");
9082
+ for (const $ of E)
9083
+ $.length > 0 ? u.push(`${g}${$}`) : u.push(l ? s : "");
9051
9084
  }
9052
9085
  i.write(`${u.join(`
9053
9086
  `)}
@@ -9137,9 +9170,9 @@ ${import_picocolors2.default.cyan(x2)}
9137
9170
  } }).prompt();
9138
9171
  };
9139
9172
  var Ke = import_picocolors2.default.magenta;
9140
- var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, cancelMessage: i, errorMessage: a, frames: o = et2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: u = et2 ? 80 : 120, signal: l, ...n } = {}) => {
9173
+ var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, cancelMessage: i, errorMessage: a, frames: o = et2 ? ["", "", "", ""] : ["", "o", "O", "0"], delay: u = et2 ? 80 : 120, signal: l, ...n } = {}) => {
9141
9174
  const c = ct2();
9142
- let g, F, p = false, E = false, $2 = "", m, h = performance.now();
9175
+ let g, F, p = false, E = false, $ = "", m, h = performance.now();
9143
9176
  const y2 = rt(s), f = n?.styleFrame ?? Ke, v = (b) => {
9144
9177
  const O2 = b > 1 ? a ?? _.messages.error : i ?? _.messages.cancel;
9145
9178
  E = b === 1, p && (L2(O2, b), E && typeof r == "function" && r());
@@ -9159,22 +9192,22 @@ var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, can
9159
9192
  const O2 = (performance.now() - b) / 1000, j2 = Math.floor(O2 / 60), G2 = Math.floor(O2 % 60);
9160
9193
  return j2 > 0 ? `[${j2}m ${G2}s]` : `[${G2}s]`;
9161
9194
  }, T2 = n.withGuide ?? _.withGuide, Y = (b = "") => {
9162
- p = true, g = Bt({ output: s }), $2 = _2(b), h = performance.now(), T2 && s.write(`${import_picocolors2.default.gray(d)}
9195
+ p = true, g = Bt({ output: s }), $ = _2(b), h = performance.now(), T2 && s.write(`${import_picocolors2.default.gray(d)}
9163
9196
  `);
9164
9197
  let O2 = 0, j2 = 0;
9165
9198
  B2(), F = setInterval(() => {
9166
- if (c && $2 === m)
9199
+ if (c && $ === m)
9167
9200
  return;
9168
- w(), m = $2;
9201
+ w(), m = $;
9169
9202
  const G2 = f(o[O2]);
9170
9203
  let tt2;
9171
9204
  if (c)
9172
- tt2 = `${G2} ${$2}...`;
9205
+ tt2 = `${G2} ${$}...`;
9173
9206
  else if (t === "timer")
9174
- tt2 = `${G2} ${$2} ${D2(h)}`;
9207
+ tt2 = `${G2} ${$} ${D2(h)}`;
9175
9208
  else {
9176
9209
  const te = ".".repeat(Math.floor(j2)).slice(0, 3);
9177
- tt2 = `${G2} ${$2}${te}`;
9210
+ tt2 = `${G2} ${$}${te}`;
9178
9211
  }
9179
9212
  const Zt = J2(tt2, y2, { hard: true, trim: false });
9180
9213
  s.write(Zt), O2 = O2 + 1 < o.length ? O2 + 1 : 0, j2 = j2 < 4 ? j2 + 0.125 : 0;
@@ -9184,17 +9217,17 @@ var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, can
9184
9217
  return;
9185
9218
  p = false, clearInterval(F), w();
9186
9219
  const G2 = O2 === 0 ? import_picocolors2.default.green(V) : O2 === 1 ? import_picocolors2.default.red(dt2) : import_picocolors2.default.red($t2);
9187
- $2 = b ?? $2, j2 || (t === "timer" ? s.write(`${G2} ${$2} ${D2(h)}
9188
- `) : s.write(`${G2} ${$2}
9220
+ $ = b ?? $, j2 || (t === "timer" ? s.write(`${G2} ${$} ${D2(h)}
9221
+ `) : s.write(`${G2} ${$}
9189
9222
  `)), A(), g();
9190
9223
  };
9191
9224
  return { start: Y, stop: (b = "") => L2(b, 0), message: (b = "") => {
9192
- $2 = _2(b ?? $2);
9225
+ $ = _2(b ?? $);
9193
9226
  }, cancel: (b = "") => L2(b, 1), error: (b = "") => L2(b, 2), clear: () => L2("", 0, true), get isCancelled() {
9194
9227
  return E;
9195
9228
  } };
9196
9229
  };
9197
- var zt = { light: C("\u2500", "-"), heavy: C("\u2501", "="), block: C("\u2588", "#") };
9230
+ var zt = { light: C("", "-"), heavy: C("", "="), block: C("", "#") };
9198
9231
  function qe({ style: t = "heavy", max: r = 100, size: s = 40, ...i } = {}) {
9199
9232
  const a = bt2(i);
9200
9233
  let o = 0, u = "";
@@ -9211,13 +9244,13 @@ function qe({ style: t = "heavy", max: r = 100, size: s = 40, ...i } = {}) {
9211
9244
  default:
9212
9245
  return import_picocolors2.default.magenta;
9213
9246
  }
9214
- }, g = (E, $2) => {
9247
+ }, g = (E, $) => {
9215
9248
  const m = Math.floor(o / l * n);
9216
- return `${c(E)(zt[t].repeat(m))}${import_picocolors2.default.dim(zt[t].repeat(n - m))} ${$2}`;
9249
+ return `${c(E)(zt[t].repeat(m))}${import_picocolors2.default.dim(zt[t].repeat(n - m))} ${$}`;
9217
9250
  }, F = (E = "") => {
9218
9251
  u = E, a.start(g("initial", E));
9219
- }, p = (E = 1, $2) => {
9220
- o = Math.min(l, E + o), a.message(g("active", $2 ?? u)), u = $2 ?? u;
9252
+ }, p = (E = 1, $) => {
9253
+ o = Math.min(l, E + o), a.message(g("active", $ ?? u)), u = $ ?? u;
9221
9254
  };
9222
9255
  return { start: F, stop: a.stop, cancel: a.cancel, error: a.error, clear: a.clear, advance: p, isCancelled: a.isCancelled, message: (E) => p(0, E) };
9223
9256
  }
@@ -10770,14 +10803,14 @@ function createApiClient(config) {
10770
10803
 
10771
10804
  // src/lib/credentials.ts
10772
10805
  import {
10773
- existsSync as existsSync4,
10806
+ existsSync as existsSync6,
10774
10807
  mkdirSync as mkdirSync2,
10775
- readFileSync as readFileSync3,
10808
+ readFileSync as readFileSync5,
10776
10809
  rmSync,
10777
10810
  writeFileSync as writeFileSync3
10778
- } from "fs";
10779
- import { homedir as homedir7 } from "os";
10780
- import { join as join8 } from "path";
10811
+ } from "node:fs";
10812
+ import { homedir as homedir7 } from "node:os";
10813
+ import { join as join8 } from "node:path";
10781
10814
  function getConfigDir() {
10782
10815
  return process.env.RUDEL_CONFIG_DIR ?? join8(homedir7(), ".rudel");
10783
10816
  }
@@ -10786,7 +10819,7 @@ function getCredentialsPath() {
10786
10819
  }
10787
10820
  function saveCredentials(token, apiBaseUrl) {
10788
10821
  const dir = getConfigDir();
10789
- if (!existsSync4(dir)) {
10822
+ if (!existsSync6(dir)) {
10790
10823
  mkdirSync2(dir, { recursive: true, mode: 448 });
10791
10824
  }
10792
10825
  const data = { token, apiBaseUrl };
@@ -10796,14 +10829,14 @@ function saveCredentials(token, apiBaseUrl) {
10796
10829
  }
10797
10830
  function loadCredentials() {
10798
10831
  const path = getCredentialsPath();
10799
- if (!existsSync4(path))
10832
+ if (!existsSync6(path))
10800
10833
  return null;
10801
- const content = readFileSync3(path, "utf-8");
10834
+ const content = readFileSync5(path, "utf-8");
10802
10835
  return JSON.parse(content);
10803
10836
  }
10804
10837
  function clearCredentials() {
10805
10838
  const path = getCredentialsPath();
10806
- if (existsSync4(path)) {
10839
+ if (existsSync6(path)) {
10807
10840
  rmSync(path);
10808
10841
  }
10809
10842
  }
@@ -10965,8 +10998,10 @@ async function pMap(iterable, mapper, {
10965
10998
  var pMapSkip = Symbol("skip");
10966
10999
 
10967
11000
  // src/lib/failed-uploads.ts
10968
- import { homedir as homedir8 } from "os";
10969
- import { join as join9 } from "path";
11001
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
11002
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
11003
+ import { homedir as homedir8 } from "node:os";
11004
+ import { dirname as dirname4, join as join9 } from "node:path";
10970
11005
 
10971
11006
  // ../../node_modules/.bun/@orpc+contract@1.13.6/node_modules/@orpc/contract/dist/shared/contract.D_dZrO__.mjs
10972
11007
  function mergeErrorMap(errorMap1, errorMap2) {
@@ -11674,10 +11709,9 @@ function normalizeSource(raw) {
11674
11709
  }
11675
11710
  async function loadFailedUploads() {
11676
11711
  try {
11677
- const file = Bun.file(FAILED_UPLOADS_PATH);
11678
- if (!await file.exists())
11712
+ if (!existsSync7(FAILED_UPLOADS_PATH))
11679
11713
  return [];
11680
- const data = await file.json();
11714
+ const data = JSON.parse(readFileSync6(FAILED_UPLOADS_PATH, "utf-8"));
11681
11715
  return data.failures.map((f) => ({
11682
11716
  ...f,
11683
11717
  source: normalizeSource(f.source)
@@ -11688,11 +11722,9 @@ async function loadFailedUploads() {
11688
11722
  }
11689
11723
  async function saveFailedUploads(failures) {
11690
11724
  try {
11691
- const { mkdir } = await import("fs/promises");
11692
- const { dirname: dirname3 } = await import("path");
11693
- await mkdir(dirname3(FAILED_UPLOADS_PATH), { recursive: true });
11725
+ await mkdir2(dirname4(FAILED_UPLOADS_PATH), { recursive: true });
11694
11726
  const data = { failures };
11695
- await Bun.write(FAILED_UPLOADS_PATH, JSON.stringify(data, null, 2));
11727
+ await writeFile2(FAILED_UPLOADS_PATH, JSON.stringify(data, null, 2));
11696
11728
  } catch {}
11697
11729
  }
11698
11730
  async function recordFailedUpload(failure) {
@@ -11813,10 +11845,9 @@ function renderBatchSummary(summary, options) {
11813
11845
  }
11814
11846
 
11815
11847
  // src/lib/project-config.ts
11816
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
11817
- import { homedir as homedir9 } from "os";
11818
- import { join as join10 } from "path";
11819
- var {$: $2 } = globalThis.Bun;
11848
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
11849
+ import { homedir as homedir9 } from "node:os";
11850
+ import { join as join10 } from "node:path";
11820
11851
  function getConfigDir2() {
11821
11852
  return process.env.RUDEL_CONFIG_DIR ?? join10(homedir9(), ".rudel");
11822
11853
  }
@@ -11825,14 +11856,14 @@ function getProjectsConfigPath() {
11825
11856
  }
11826
11857
  function loadProjectsConfig() {
11827
11858
  const path = getProjectsConfigPath();
11828
- if (!existsSync5(path))
11859
+ if (!existsSync8(path))
11829
11860
  return { projects: {} };
11830
- const content = readFileSync4(path, "utf-8");
11861
+ const content = readFileSync7(path, "utf-8");
11831
11862
  return JSON.parse(content);
11832
11863
  }
11833
11864
  function saveProjectsConfig(config) {
11834
11865
  const dir = getConfigDir2();
11835
- if (!existsSync5(dir)) {
11866
+ if (!existsSync8(dir)) {
11836
11867
  mkdirSync3(dir, { recursive: true, mode: 448 });
11837
11868
  }
11838
11869
  writeFileSync4(getProjectsConfigPath(), JSON.stringify(config, null, 2), {
@@ -11841,16 +11872,27 @@ function saveProjectsConfig(config) {
11841
11872
  }
11842
11873
  async function getProjectKey(cwd) {
11843
11874
  try {
11844
- const result = await $2`git -C ${cwd} remote get-url origin`.quiet();
11875
+ const result = await exec("git", [
11876
+ "-C",
11877
+ cwd,
11878
+ "remote",
11879
+ "get-url",
11880
+ "origin"
11881
+ ]);
11845
11882
  if (result.exitCode === 0) {
11846
- const url = result.text().trim();
11883
+ const url = result.stdout.trim();
11847
11884
  return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
11848
11885
  }
11849
11886
  } catch {}
11850
11887
  try {
11851
- const result = await $2`git -C ${cwd} rev-parse --show-toplevel`.quiet();
11888
+ const result = await exec("git", [
11889
+ "-C",
11890
+ cwd,
11891
+ "rev-parse",
11892
+ "--show-toplevel"
11893
+ ]);
11852
11894
  if (result.exitCode === 0) {
11853
- return result.text().trim();
11895
+ return result.stdout.trim();
11854
11896
  }
11855
11897
  } catch {}
11856
11898
  return cwd;
@@ -13058,7 +13100,7 @@ var exports_util_node = {};
13058
13100
  __export(exports_util_node, {
13059
13101
  inspect: () => inspect
13060
13102
  });
13061
- import util3 from "util";
13103
+ import util3 from "node:util";
13062
13104
  function inspect(obj, options) {
13063
13105
  return util3.inspect(obj, options);
13064
13106
  }
@@ -13234,7 +13276,7 @@ function getTextFormatter(options = {}) {
13234
13276
  else
13235
13277
  return tsOption;
13236
13278
  })();
13237
- const categorySeparator = options.category ?? "\xB7";
13279
+ const categorySeparator = options.category ?? "·";
13238
13280
  const valueRenderer = options.value ? (v) => options.value(v, inspect2) : inspect2;
13239
13281
  const levelRenderer = (() => {
13240
13282
  const levelOption = options.level;
@@ -13454,7 +13496,7 @@ function defaultConsoleFormatter(record) {
13454
13496
  const date = new Date(record.timestamp);
13455
13497
  const time = `${date.getUTCHours().toString().padStart(2, "0")}:${date.getUTCMinutes().toString().padStart(2, "0")}:${date.getUTCSeconds().toString().padStart(2, "0")}.${date.getUTCMilliseconds().toString().padStart(3, "0")}`;
13456
13498
  return [
13457
- `%c${time} %c${levelAbbreviations[record.level]}%c %c${record.category.join("\xB7")} %c${msg}`,
13499
+ `%c${time} %c${levelAbbreviations[record.level]}%c %c${record.category.join("·")} %c${msg}`,
13458
13500
  "color: gray;",
13459
13501
  logLevelStyles[record.level],
13460
13502
  "background-color: default;",
@@ -13665,8 +13707,8 @@ var ConfigError = class extends Error {
13665
13707
  };
13666
13708
 
13667
13709
  // src/logging.ts
13668
- import { homedir as homedir10 } from "os";
13669
- import { join as join12 } from "path";
13710
+ import { homedir as homedir10 } from "node:os";
13711
+ import { join as join12 } from "node:path";
13670
13712
 
13671
13713
  // ../../node_modules/.bun/@logtape+file@2.0.4+2d5de51540e256d2/node_modules/@logtape/file/dist/filesink.base.js
13672
13714
  var AdaptiveFlushStrategy = class {
@@ -13931,9 +13973,9 @@ function getBaseFileSink(path, options) {
13931
13973
  }
13932
13974
 
13933
13975
  // ../../node_modules/.bun/@logtape+file@2.0.4+2d5de51540e256d2/node_modules/@logtape/file/dist/filesink.node.js
13934
- import fs from "fs";
13935
- import { join as join11 } from "path";
13936
- import { promisify } from "util";
13976
+ import fs from "node:fs";
13977
+ import { join as join11 } from "node:path";
13978
+ import { promisify } from "node:util";
13937
13979
  var nodeDriver = {
13938
13980
  openSync(path) {
13939
13981
  return fs.openSync(path, "a");
@@ -13997,8 +14039,8 @@ function getFileSink(path, options = {}) {
13997
14039
  var LOG_DIR = join12(homedir10(), ".rudel", "logs");
13998
14040
  var LOG_FILE = join12(LOG_DIR, "hook-upload.log");
13999
14041
  async function setupHookLogging() {
14000
- const { mkdir } = await import("fs/promises");
14001
- await mkdir(LOG_DIR, { recursive: true }).catch(() => {});
14042
+ const { mkdir: mkdir3 } = await import("node:fs/promises");
14043
+ await mkdir3(LOG_DIR, { recursive: true }).catch(() => {});
14002
14044
  await configure({
14003
14045
  sinks: {
14004
14046
  file: getFileSink(LOG_FILE)
@@ -14181,7 +14223,11 @@ var hooksRouteMap = buildRouteMap({
14181
14223
  });
14182
14224
 
14183
14225
  // src/commands/login.ts
14184
- import { randomBytes } from "crypto";
14226
+ import { spawn } from "node:child_process";
14227
+ import { randomBytes } from "node:crypto";
14228
+ import {
14229
+ createServer
14230
+ } from "node:http";
14185
14231
  var DEFAULT_API_BASE = "https://app.rudel.ai";
14186
14232
  var DEFAULT_WEB_URL = "https://app.rudel.ai";
14187
14233
  var CALLBACK_TIMEOUT_MS = 120000;
@@ -14200,41 +14246,53 @@ async function runLogin(flags) {
14200
14246
  resolveCallback = resolve2;
14201
14247
  rejectCallback = reject;
14202
14248
  });
14203
- const server = Bun.serve({
14204
- port: 0,
14205
- hostname: "127.0.0.1",
14206
- fetch(request) {
14207
- const url = new URL(request.url);
14208
- if (url.pathname !== "/callback") {
14209
- return new Response("Not found", { status: 404 });
14210
- }
14211
- const receivedToken = url.searchParams.get("token");
14212
- const receivedState = url.searchParams.get("state");
14213
- if (receivedState !== state) {
14214
- rejectCallback(new Error("State mismatch \u2014 possible CSRF attack"));
14215
- return new Response("<html><body><h1>Login failed</h1><p>State mismatch. Please try again.</p></body></html>", { headers: { "Content-Type": "text/html" } });
14216
- }
14217
- if (!receivedToken) {
14218
- rejectCallback(new Error("No token received"));
14219
- return new Response("<html><body><h1>Login failed</h1><p>No token received.</p></body></html>", { headers: { "Content-Type": "text/html" } });
14220
- }
14221
- resolveCallback(receivedToken);
14222
- return new Response("<html><body><h1>Login successful!</h1><p>You can close this tab and return to the terminal.</p></body></html>", { headers: { "Content-Type": "text/html" } });
14249
+ const server = createServer((req, res) => {
14250
+ const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
14251
+ if (url.pathname !== "/callback") {
14252
+ res.writeHead(404, { "Content-Type": "text/plain" });
14253
+ res.end("Not found");
14254
+ return;
14255
+ }
14256
+ const receivedToken = url.searchParams.get("token");
14257
+ const receivedState = url.searchParams.get("state");
14258
+ if (receivedState !== state) {
14259
+ rejectCallback(new Error("State mismatch — possible CSRF attack"));
14260
+ res.writeHead(200, { "Content-Type": "text/html" });
14261
+ res.end("<html><body><h1>Login failed</h1><p>State mismatch. Please try again.</p></body></html>");
14262
+ return;
14223
14263
  }
14264
+ if (!receivedToken) {
14265
+ rejectCallback(new Error("No token received"));
14266
+ res.writeHead(200, { "Content-Type": "text/html" });
14267
+ res.end("<html><body><h1>Login failed</h1><p>No token received.</p></body></html>");
14268
+ return;
14269
+ }
14270
+ resolveCallback(receivedToken);
14271
+ res.writeHead(200, { "Content-Type": "text/html" });
14272
+ res.end("<html><body><h1>Login successful!</h1><p>You can close this tab and return to the terminal.</p></body></html>");
14273
+ });
14274
+ await new Promise((resolve2) => {
14275
+ server.listen(0, "127.0.0.1", resolve2);
14224
14276
  });
14225
- const callbackUrl = `http://127.0.0.1:${server.port}/callback`;
14277
+ const port = server.address().port;
14278
+ const callbackUrl = `http://127.0.0.1:${port}/callback`;
14226
14279
  const loginUrl = `${flags.webUrl}?cli_callback=${encodeURIComponent(callbackUrl)}&state=${state}`;
14227
14280
  R2.info(`If the browser doesn't open, visit:
14228
14281
  ${loginUrl}`);
14229
14282
  if (!flags.noBrowser) {
14230
14283
  if (process.platform === "win32") {
14231
- Bun.spawn(["cmd", "/c", "start", "", loginUrl], {
14232
- stdout: "ignore",
14233
- stderr: "ignore"
14284
+ const child = spawn("cmd", ["/c", "start", "", loginUrl], {
14285
+ detached: true,
14286
+ stdio: "ignore"
14234
14287
  });
14288
+ child.unref();
14235
14289
  } else {
14236
14290
  const opener = process.platform === "darwin" ? "open" : "xdg-open";
14237
- Bun.spawn([opener, loginUrl], { stdout: "ignore", stderr: "ignore" });
14291
+ const child = spawn(opener, [loginUrl], {
14292
+ detached: true,
14293
+ stdio: "ignore"
14294
+ });
14295
+ child.unref();
14238
14296
  }
14239
14297
  }
14240
14298
  const timeout = setTimeout(() => {
@@ -14247,14 +14305,14 @@ ${loginUrl}`);
14247
14305
  token = await tokenPromise;
14248
14306
  } catch (error) {
14249
14307
  clearTimeout(timeout);
14250
- server.stop();
14308
+ server.close();
14251
14309
  spin.stop("Authentication failed");
14252
14310
  R2.error(error instanceof Error ? error.message : String(error));
14253
14311
  process.exitCode = 1;
14254
14312
  return;
14255
14313
  }
14256
14314
  clearTimeout(timeout);
14257
- server.stop();
14315
+ server.close();
14258
14316
  spin.message("Validating token...");
14259
14317
  const meResponse = await fetch(`${flags.apiBase}/rpc/me`, {
14260
14318
  method: "POST",
@@ -14376,9 +14434,9 @@ var setOrgCommand = buildCommand({
14376
14434
  });
14377
14435
 
14378
14436
  // src/lib/classifier.ts
14379
- import { mkdir, unlink } from "fs/promises";
14380
- import { homedir as homedir11 } from "os";
14381
- import { join as join13 } from "path";
14437
+ import { mkdir as mkdir3, unlink, writeFile as writeFile3 } from "node:fs/promises";
14438
+ import { homedir as homedir11 } from "node:os";
14439
+ import { join as join13 } from "node:path";
14382
14440
 
14383
14441
  // src/lib/types.ts
14384
14442
  var SESSION_TAGS = [
@@ -14408,24 +14466,21 @@ async function classifySession(content) {
14408
14466
  const tempDir = join13(homedir11(), ".claude", "temp");
14409
14467
  const tempFile = join13(tempDir, `classify-${Date.now()}.txt`);
14410
14468
  try {
14411
- await mkdir(tempDir, { recursive: true });
14412
- await Bun.write(tempFile, `Classify this session transcript:
14469
+ await mkdir3(tempDir, { recursive: true });
14470
+ await writeFile3(tempFile, `Classify this session transcript:
14413
14471
 
14414
14472
  ${truncatedContent}`);
14415
14473
  const prompt = `Read and classify the session transcript in this file: ${tempFile}`;
14416
14474
  const escapedPrompt = prompt.replace(/'/g, "'\\''");
14417
14475
  const escapedSystemPrompt = SYSTEM_PROMPT.replace(/'/g, "'\\''");
14418
- const proc = Bun.spawn([
14419
- "sh",
14476
+ const result = await exec("sh", [
14420
14477
  "-c",
14421
14478
  `echo '${escapedPrompt}' | claude --output-format text --print --model haiku --no-session-persistence --dangerously-skip-permissions --system-prompt '${escapedSystemPrompt}'`
14422
- ], { stdout: "pipe", stderr: "pipe" });
14423
- const exitCode = await proc.exited;
14424
- const stdout = await new Response(proc.stdout).text();
14425
- if (exitCode !== 0) {
14479
+ ]);
14480
+ if (result.exitCode !== 0) {
14426
14481
  return "other";
14427
14482
  }
14428
- const output = stdout.trim().toLowerCase();
14483
+ const output = result.stdout.trim().toLowerCase();
14429
14484
  if (SESSION_TAGS.includes(output)) {
14430
14485
  return output;
14431
14486
  }
@@ -14445,9 +14500,9 @@ ${truncatedContent}`);
14445
14500
  }
14446
14501
 
14447
14502
  // src/lib/session-resolver.ts
14448
- import { access, readdir as readdir3 } from "fs/promises";
14449
- import { homedir as homedir12 } from "os";
14450
- import { basename, dirname as dirname3, join as join14 } from "path";
14503
+ import { access, readdir as readdir3 } from "node:fs/promises";
14504
+ import { homedir as homedir12 } from "node:os";
14505
+ import { basename, dirname as dirname5, join as join14 } from "node:path";
14451
14506
  var SESSIONS_BASE_DIR3 = join14(homedir12(), ".claude", "projects");
14452
14507
  async function resolveSession(input) {
14453
14508
  const isPath = input.includes("/") || input.endsWith(".jsonl");
@@ -14465,7 +14520,7 @@ async function resolveFromPath(filePath) {
14465
14520
  throw new Error(`Session file not found: ${filePath}`);
14466
14521
  }
14467
14522
  const sessionId = filename.replace(/\.jsonl$/, "");
14468
- const sessionDir = dirname3(filePath);
14523
+ const sessionDir = dirname5(filePath);
14469
14524
  const parentDir = basename(sessionDir);
14470
14525
  const projectPath = await decodeProjectPath(parentDir);
14471
14526
  return { transcriptPath: filePath, projectPath, sessionDir, sessionId };
@@ -14595,7 +14650,7 @@ async function runInteractiveUpload(flags) {
14595
14650
  });
14596
14651
  renderBatchSummary(summary, { showRetryHint: summary.failed > 0 });
14597
14652
  if (flags.dryRun) {
14598
- Le("Dry run complete \u2014 no sessions were uploaded.");
14653
+ Le("Dry run complete no sessions were uploaded.");
14599
14654
  } else {
14600
14655
  Le("Done!");
14601
14656
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rudel",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "CLI for the Coding Agent Analytics Platform rudel.ai",
6
6
  "license": "MIT",
@@ -32,7 +32,7 @@
32
32
  "scripts": {
33
33
  "dev": "bun run src/bin/cli.ts",
34
34
  "check-types": "tsc --noEmit",
35
- "build": "bun build src/bin/cli.ts --outdir dist --target bun",
35
+ "build": "bun build src/bin/cli.ts --outdir dist --target node",
36
36
  "test": "bun test"
37
37
  },
38
38
  "dependencies": {
@@ -48,6 +48,7 @@
48
48
  "@rudel/agent-adapters": "0.0.0",
49
49
  "@rudel/api-routes": "0.0.0",
50
50
  "@rudel/typescript-config": "0.0.0",
51
+ "@types/node": "^22",
51
52
  "bun-types": "latest",
52
53
  "typescript": "5.9.2"
53
54
  }