rudel 0.2.0 → 0.2.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.
Files changed (2) hide show
  1. package/dist/cli.js +87 -54
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
2
  var __create = Object.create;
4
3
  var __getProtoOf = Object.getPrototypeOf;
5
4
  var __defProp = Object.defineProperty;
@@ -26,7 +25,6 @@ var __export = (target, all) => {
26
25
  set: (newValue) => all[name] = () => newValue
27
26
  });
28
27
  };
29
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
28
 
31
29
  // ../../node_modules/sisteransi/src/index.js
32
30
  var require_src = __commonJS((exports, module) => {
@@ -1889,7 +1887,7 @@ async function run(app, inputs, context) {
1889
1887
  // package.json
1890
1888
  var package_default = {
1891
1889
  name: "rudel",
1892
- version: "0.2.0",
1890
+ version: "0.2.1",
1893
1891
  type: "module",
1894
1892
  description: "CLI for the Coding Agent Analytics Platform rudel.ai",
1895
1893
  license: "MIT",
@@ -7795,7 +7793,8 @@ function exec(cmd, args) {
7795
7793
 
7796
7794
  // src/lib/git-info.ts
7797
7795
  function normalizeRemoteUrl(url) {
7798
- return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7796
+ const sanitizedUrl = url.replace(/^([a-z][a-z\d+.-]*:\/\/)[^/]+@/i, "$1");
7797
+ return sanitizedUrl.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7799
7798
  }
7800
7799
  async function getGitInfo(cwd) {
7801
7800
  const [remoteUrl, branch, sha, packageInfo] = await Promise.all([
@@ -7919,15 +7918,43 @@ async function getGitSha(cwd) {
7919
7918
 
7920
7919
  // src/lib/remote-cache.ts
7921
7920
  import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
7922
- import { mkdir, writeFile } from "node:fs/promises";
7921
+ import { join as join8 } from "node:path";
7922
+
7923
+ // src/lib/local-state.ts
7924
+ import { chmod, mkdir, writeFile } from "node:fs/promises";
7923
7925
  import { homedir as homedir5 } from "node:os";
7924
7926
  import { dirname as dirname3, join as join7 } from "node:path";
7925
- var CACHE_PATH = join7(homedir5(), ".rudel", "remote-cache.json");
7927
+ var PRIVATE_DIRECTORY_MODE = 448;
7928
+ var PRIVATE_FILE_MODE = 384;
7929
+ function getRudelConfigDir() {
7930
+ return process.env.RUDEL_CONFIG_DIR ?? join7(homedir5(), ".rudel");
7931
+ }
7932
+ async function ensurePrivateFile(filePath, configDir) {
7933
+ await secureDirectory(configDir);
7934
+ const fileDirectory = dirname3(filePath);
7935
+ if (fileDirectory !== configDir) {
7936
+ await secureDirectory(fileDirectory);
7937
+ }
7938
+ await writeFile(filePath, "", { flag: "a", mode: PRIVATE_FILE_MODE });
7939
+ await chmod(filePath, PRIVATE_FILE_MODE);
7940
+ }
7941
+ async function writePrivateFile(filePath, content, configDir) {
7942
+ await ensurePrivateFile(filePath, configDir);
7943
+ await writeFile(filePath, content, "utf8");
7944
+ }
7945
+ async function secureDirectory(path) {
7946
+ await mkdir(path, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
7947
+ await chmod(path, PRIVATE_DIRECTORY_MODE);
7948
+ }
7949
+
7950
+ // src/lib/remote-cache.ts
7926
7951
  async function getRemoteCache() {
7927
7952
  try {
7928
- if (!existsSync5(CACHE_PATH))
7953
+ const path = getRemoteCachePath();
7954
+ if (!existsSync5(path))
7929
7955
  return {};
7930
- return JSON.parse(readFileSync4(CACHE_PATH, "utf-8"));
7956
+ await ensurePrivateFile(path, getRudelConfigDir());
7957
+ return JSON.parse(readFileSync4(path, "utf-8"));
7931
7958
  } catch {
7932
7959
  return {};
7933
7960
  }
@@ -7940,10 +7967,12 @@ function cacheRemote(cache, encodedDir, normalizedRemote) {
7940
7967
  }
7941
7968
  async function cacheRemotes(cache) {
7942
7969
  try {
7943
- await mkdir(dirname3(CACHE_PATH), { recursive: true });
7944
- await writeFile(CACHE_PATH, JSON.stringify(cache));
7970
+ await writePrivateFile(getRemoteCachePath(), JSON.stringify(cache), getRudelConfigDir());
7945
7971
  } catch {}
7946
7972
  }
7973
+ function getRemoteCachePath() {
7974
+ return join8(getRudelConfigDir(), "remote-cache.json");
7975
+ }
7947
7976
 
7948
7977
  // src/lib/project-grouping.ts
7949
7978
  async function scanAndGroupProjects(cwd = process.cwd()) {
@@ -11827,12 +11856,12 @@ import {
11827
11856
  writeFileSync as writeFileSync3
11828
11857
  } from "node:fs";
11829
11858
  import { homedir as homedir7 } from "node:os";
11830
- import { join as join8 } from "node:path";
11859
+ import { join as join9 } from "node:path";
11831
11860
  function getConfigDir() {
11832
- return process.env.RUDEL_CONFIG_DIR ?? join8(homedir7(), ".rudel");
11861
+ return process.env.RUDEL_CONFIG_DIR ?? join9(homedir7(), ".rudel");
11833
11862
  }
11834
11863
  function getCredentialsPath() {
11835
- return join8(getConfigDir(), "credentials.json");
11864
+ return join9(getConfigDir(), "credentials.json");
11836
11865
  }
11837
11866
  function saveCredentials(credentials) {
11838
11867
  const dir = getConfigDir();
@@ -13875,12 +13904,9 @@ var pMapSkip = Symbol("skip");
13875
13904
 
13876
13905
  // src/lib/failed-uploads.ts
13877
13906
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
13878
- import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
13879
- import { homedir as homedir8 } from "node:os";
13880
- import { dirname as dirname4, join as join9 } from "node:path";
13907
+ import { join as join10 } from "node:path";
13881
13908
  function getFailedUploadsPath() {
13882
- const configDir = process.env.RUDEL_CONFIG_DIR ?? join9(homedir8(), ".rudel");
13883
- return join9(configDir, "failed-uploads.json");
13909
+ return join10(getRudelConfigDir(), "failed-uploads.json");
13884
13910
  }
13885
13911
  function normalizeSource(raw) {
13886
13912
  if (typeof raw !== "string")
@@ -13894,6 +13920,7 @@ async function loadFailedUploads() {
13894
13920
  const path = getFailedUploadsPath();
13895
13921
  if (!existsSync7(path))
13896
13922
  return [];
13923
+ await ensurePrivateFile(path, getRudelConfigDir());
13897
13924
  const data = JSON.parse(readFileSync6(path, "utf-8"));
13898
13925
  return data.failures.map((f) => ({
13899
13926
  ...f,
@@ -13906,9 +13933,8 @@ async function loadFailedUploads() {
13906
13933
  async function saveFailedUploads(failures) {
13907
13934
  try {
13908
13935
  const path = getFailedUploadsPath();
13909
- await mkdir2(dirname4(path), { recursive: true });
13910
13936
  const data = { failures };
13911
- await writeFile2(path, JSON.stringify(data, null, 2));
13937
+ await writePrivateFile(path, JSON.stringify(data, null, 2), getRudelConfigDir());
13912
13938
  } catch {}
13913
13939
  }
13914
13940
  async function recordFailedUpload(failure) {
@@ -14392,11 +14418,11 @@ function renderBatchSummary(summary, options) {
14392
14418
  // src/lib/product-analytics.ts
14393
14419
  import { randomUUID } from "node:crypto";
14394
14420
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
14395
- import { homedir as homedir9 } from "node:os";
14396
- import { join as join10 } from "node:path";
14421
+ import { homedir as homedir8 } from "node:os";
14422
+ import { join as join11 } from "node:path";
14397
14423
 
14398
14424
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
14399
- import { dirname as dirname5, posix, sep } from "path";
14425
+ import { dirname as dirname4, posix, sep } from "path";
14400
14426
  function createModulerModifier() {
14401
14427
  const getModuleFromFileName = createGetModuleFromFilename();
14402
14428
  return async (frames) => {
@@ -14405,7 +14431,7 @@ function createModulerModifier() {
14405
14431
  return frames;
14406
14432
  };
14407
14433
  }
14408
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname5(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
14434
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname4(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
14409
14435
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
14410
14436
  return (filename) => {
14411
14437
  if (!filename)
@@ -18865,10 +18891,10 @@ function getClient() {
18865
18891
  return client;
18866
18892
  }
18867
18893
  function getConfigDir2() {
18868
- return process.env.RUDEL_CONFIG_DIR ?? join10(homedir9(), ".rudel");
18894
+ return process.env.RUDEL_CONFIG_DIR ?? join11(homedir8(), ".rudel");
18869
18895
  }
18870
18896
  function getAnalyticsStatePath() {
18871
- return join10(getConfigDir2(), ANALYTICS_STATE_FILE);
18897
+ return join11(getConfigDir2(), ANALYTICS_STATE_FILE);
18872
18898
  }
18873
18899
  function readAnalyticsState() {
18874
18900
  const statePath = getAnalyticsStatePath();
@@ -19021,30 +19047,37 @@ function getBaseCliEventPayload() {
19021
19047
  var CliProductAnalyticsEvents = PRODUCT_ANALYTICS_EVENTS;
19022
19048
 
19023
19049
  // src/lib/project-config.ts
19024
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
19025
- import { homedir as homedir10 } from "node:os";
19026
- import { join as join11 } from "node:path";
19050
+ import {
19051
+ chmodSync,
19052
+ existsSync as existsSync9,
19053
+ mkdirSync as mkdirSync4,
19054
+ readFileSync as readFileSync8,
19055
+ writeFileSync as writeFileSync5
19056
+ } from "node:fs";
19057
+ import { homedir as homedir9 } from "node:os";
19058
+ import { join as join12 } from "node:path";
19027
19059
  function getConfigDir3() {
19028
- return process.env.RUDEL_CONFIG_DIR ?? join11(homedir10(), ".rudel");
19060
+ return process.env.RUDEL_CONFIG_DIR ?? join12(homedir9(), ".rudel");
19029
19061
  }
19030
19062
  function getProjectsConfigPath() {
19031
- return join11(getConfigDir3(), "projects.json");
19063
+ return join12(getConfigDir3(), "projects.json");
19032
19064
  }
19033
19065
  function loadProjectsConfig() {
19034
19066
  const path = getProjectsConfigPath();
19035
19067
  if (!existsSync9(path))
19036
19068
  return { projects: {} };
19069
+ chmodSync(getConfigDir3(), 448);
19070
+ chmodSync(path, 384);
19037
19071
  const content = readFileSync8(path, "utf-8");
19038
19072
  return JSON.parse(content);
19039
19073
  }
19040
19074
  function saveProjectsConfig(config) {
19041
19075
  const dir = getConfigDir3();
19042
- if (!existsSync9(dir)) {
19043
- mkdirSync4(dir, { recursive: true, mode: 448 });
19044
- }
19045
- writeFileSync5(getProjectsConfigPath(), JSON.stringify(config, null, 2), {
19046
- mode: 384
19047
- });
19076
+ mkdirSync4(dir, { recursive: true, mode: 448 });
19077
+ chmodSync(dir, 448);
19078
+ const path = getProjectsConfigPath();
19079
+ writeFileSync5(path, JSON.stringify(config, null, 2), { mode: 384 });
19080
+ chmodSync(path, 384);
19048
19081
  }
19049
19082
  async function getProjectKey(cwd) {
19050
19083
  try {
@@ -19057,7 +19090,9 @@ async function getProjectKey(cwd) {
19057
19090
  ]);
19058
19091
  if (result.exitCode === 0) {
19059
19092
  const url = result.stdout.trim();
19060
- return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
19093
+ if (url.length > 0) {
19094
+ return normalizeRemoteUrl(url);
19095
+ }
19061
19096
  }
19062
19097
  } catch {}
19063
19098
  try {
@@ -20919,8 +20954,7 @@ async function reportHookUploadFailure(logger2, result, failure) {
20919
20954
  }
20920
20955
 
20921
20956
  // src/logging.ts
20922
- import { homedir as homedir11 } from "node:os";
20923
- import { join as join13 } from "node:path";
20957
+ import { join as join14 } from "node:path";
20924
20958
 
20925
20959
  // ../../node_modules/@logtape/file/dist/filesink.base.js
20926
20960
  var AdaptiveFlushStrategy = class {
@@ -21186,7 +21220,7 @@ function getBaseFileSink(path, options) {
21186
21220
 
21187
21221
  // ../../node_modules/@logtape/file/dist/filesink.node.js
21188
21222
  import fs from "node:fs";
21189
- import { join as join12 } from "node:path";
21223
+ import { join as join13 } from "node:path";
21190
21224
  import { promisify } from "node:util";
21191
21225
  var nodeDriver = {
21192
21226
  openSync(path) {
@@ -21226,14 +21260,14 @@ var nodeTimeDriver = {
21226
21260
  readdirSync: fs.readdirSync,
21227
21261
  unlinkSync: fs.unlinkSync,
21228
21262
  mkdirSync: fs.mkdirSync,
21229
- joinPath: join12
21263
+ joinPath: join13
21230
21264
  };
21231
21265
  var nodeAsyncTimeDriver = {
21232
21266
  ...nodeAsyncDriver,
21233
21267
  readdirSync: fs.readdirSync,
21234
21268
  unlinkSync: fs.unlinkSync,
21235
21269
  mkdirSync: fs.mkdirSync,
21236
- joinPath: join12
21270
+ joinPath: join13
21237
21271
  };
21238
21272
  function getFileSink(path, options = {}) {
21239
21273
  if (options.nonBlocking)
@@ -21248,14 +21282,13 @@ function getFileSink(path, options = {}) {
21248
21282
  }
21249
21283
 
21250
21284
  // src/logging.ts
21251
- var LOG_DIR = join13(homedir11(), ".rudel", "logs");
21252
- var LOG_FILE = join13(LOG_DIR, "hook-upload.log");
21253
21285
  async function setupHookLogging() {
21254
- const { mkdir: mkdir3 } = await import("node:fs/promises");
21255
- await mkdir3(LOG_DIR, { recursive: true }).catch(() => {});
21286
+ const configDir = getRudelConfigDir();
21287
+ const logFile = join14(configDir, "logs", "hook-upload.log");
21288
+ await ensurePrivateFile(logFile, configDir);
21256
21289
  await configure({
21257
21290
  sinks: {
21258
- file: getFileSink(LOG_FILE)
21291
+ file: getFileSink(logFile)
21259
21292
  },
21260
21293
  loggers: [
21261
21294
  {
@@ -21924,9 +21957,9 @@ function execWithStdin(cmd, args, stdin) {
21924
21957
 
21925
21958
  // src/lib/session-resolver.ts
21926
21959
  import { access, readdir as readdir3 } from "node:fs/promises";
21927
- import { homedir as homedir12 } from "node:os";
21928
- import { basename, dirname as dirname6, join as join14 } from "node:path";
21929
- var SESSIONS_BASE_DIR3 = join14(homedir12(), ".claude", "projects");
21960
+ import { homedir as homedir10 } from "node:os";
21961
+ import { basename, dirname as dirname5, join as join15 } from "node:path";
21962
+ var SESSIONS_BASE_DIR3 = join15(homedir10(), ".claude", "projects");
21930
21963
  async function resolveSession(input) {
21931
21964
  const isPath = input.includes("/") || input.endsWith(".jsonl");
21932
21965
  if (isPath) {
@@ -21943,7 +21976,7 @@ async function resolveFromPath(filePath) {
21943
21976
  throw new Error(`Session file not found: ${filePath}`);
21944
21977
  }
21945
21978
  const sessionId = filename.replace(/\.jsonl$/, "");
21946
- const sessionDir = dirname6(filePath);
21979
+ const sessionDir = dirname5(filePath);
21947
21980
  const parentDir = basename(sessionDir);
21948
21981
  const projectPath = await decodeProjectPath(parentDir);
21949
21982
  return { transcriptPath: filePath, projectPath, sessionDir, sessionId };
@@ -21958,11 +21991,11 @@ async function resolveFromId(sessionId) {
21958
21991
  throw new Error(`Session not found: ${sessionId}`);
21959
21992
  }
21960
21993
  for (const projectDir of projectDirs) {
21961
- const sessionDir = join14(SESSIONS_BASE_DIR3, projectDir);
21994
+ const sessionDir = join15(SESSIONS_BASE_DIR3, projectDir);
21962
21995
  try {
21963
21996
  const files = await readdir3(sessionDir);
21964
21997
  if (files.includes(sessionFileName)) {
21965
- const transcriptPath = join14(sessionDir, sessionFileName);
21998
+ const transcriptPath = join15(sessionDir, sessionFileName);
21966
21999
  const projectPath = await decodeProjectPath(projectDir);
21967
22000
  return {
21968
22001
  transcriptPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rudel",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "CLI for the Coding Agent Analytics Platform rudel.ai",
6
6
  "license": "MIT",