@wrongstack/tools 0.6.0 → 0.6.3

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/builtin.js CHANGED
@@ -5,15 +5,11 @@ import { dirname } from 'path';
5
5
  import * as os from 'os';
6
6
  import { statSync } from 'fs';
7
7
  import * as fs9 from 'fs/promises';
8
+ import { stat } from 'fs/promises';
8
9
  import * as dns from 'dns/promises';
9
10
  import * as net from 'net';
10
11
 
11
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
12
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
13
- }) : x)(function(x) {
14
- if (typeof require !== "undefined") return require.apply(this, arguments);
15
- throw Error('Dynamic require of "' + x + '" is not supported');
16
- });
12
+ // src/_spawn-stream.ts
17
13
  async function* spawnStream(opts) {
18
14
  const max = opts.maxBytes ?? 2e5;
19
15
  const flushAt = opts.flushBytes ?? 4 * 1024;
@@ -173,14 +169,14 @@ var auditTool = {
173
169
  }
174
170
  };
175
171
  async function detectManager(cwd) {
176
- const { stat: stat9 } = await import('fs/promises');
172
+ const { stat: stat10 } = await import('fs/promises');
177
173
  try {
178
- await stat9(`${cwd}/pnpm-lock.yaml`);
174
+ await stat10(`${cwd}/pnpm-lock.yaml`);
179
175
  return "pnpm";
180
176
  } catch {
181
177
  }
182
178
  try {
183
- await stat9(`${cwd}/yarn.lock`);
179
+ await stat10(`${cwd}/yarn.lock`);
184
180
  return "yarn";
185
181
  } catch {
186
182
  }
@@ -966,8 +962,8 @@ function findGitDir(cwd) {
966
962
  let dir = cwd;
967
963
  for (let i = 0; i < 20; i++) {
968
964
  try {
969
- const stat9 = statSync(path.join(dir, ".git"));
970
- if (stat9.isDirectory()) return dir;
965
+ const stat10 = statSync(path.join(dir, ".git"));
966
+ if (stat10.isDirectory()) return dir;
971
967
  } catch {
972
968
  }
973
969
  const parent = path.dirname(dir);
@@ -1006,8 +1002,8 @@ async function fileDiff(input, ctx, signal) {
1006
1002
  const results = [];
1007
1003
  for (const file of files) {
1008
1004
  const absPath = safeResolve(file, ctx);
1009
- const stat9 = await fs9.stat(absPath).catch(() => null);
1010
- if (!stat9?.isFile()) continue;
1005
+ const stat10 = await fs9.stat(absPath).catch(() => null);
1006
+ if (!stat10?.isFile()) continue;
1011
1007
  const content = await fs9.readFile(absPath, "utf8");
1012
1008
  const lines = content.split(/\r?\n/);
1013
1009
  results.push(`--- ${file}
@@ -1105,8 +1101,8 @@ async function resolveFiles(filesInput, cwd) {
1105
1101
  for (const f of files) {
1106
1102
  const absPath = f.trim().startsWith("/") ? f.trim() : `${cwd}/${f.trim()}`;
1107
1103
  try {
1108
- const stat9 = await fs9.stat(absPath);
1109
- if (stat9.isFile()) resolved.push(absPath);
1104
+ const stat10 = await fs9.stat(absPath);
1105
+ if (stat10.isFile()) resolved.push(absPath);
1110
1106
  } catch {
1111
1107
  }
1112
1108
  }
@@ -1197,13 +1193,13 @@ var editTool = {
1197
1193
  if (input.new_string === void 0) throw new Error("edit: new_string is required");
1198
1194
  if (input.old_string === "") throw new Error("edit: old_string cannot be empty");
1199
1195
  const absPath = safeResolve(input.path, ctx);
1200
- const stat9 = await fs9.stat(absPath).catch((err) => {
1196
+ const stat10 = await fs9.stat(absPath).catch((err) => {
1201
1197
  if (err.code === "ENOENT") {
1202
1198
  throw new Error(`edit: file "${input.path}" does not exist. Use \`write\` instead.`);
1203
1199
  }
1204
1200
  throw err;
1205
1201
  });
1206
- if (!stat9.isFile()) throw new Error(`edit: "${input.path}" is not a regular file`);
1202
+ if (!stat10.isFile()) throw new Error(`edit: "${input.path}" is not a regular file`);
1207
1203
  if (!ctx.hasRead(absPath)) {
1208
1204
  throw new Error(`edit: file "${input.path}" was not read in this session. Read it first.`);
1209
1205
  }
@@ -1895,13 +1891,13 @@ var formatTool = {
1895
1891
  }
1896
1892
  };
1897
1893
  async function detectFixer(cwd) {
1898
- const { stat: stat9 } = await import('fs/promises');
1894
+ const { stat: stat10 } = await import('fs/promises');
1899
1895
  try {
1900
- await stat9(`${cwd}/biome.json`);
1896
+ await stat10(`${cwd}/biome.json`);
1901
1897
  return "biome";
1902
1898
  } catch {
1903
1899
  try {
1904
- await stat9(`${cwd}/.prettierrc`);
1900
+ await stat10(`${cwd}/.prettierrc`);
1905
1901
  return "prettier";
1906
1902
  } catch {
1907
1903
  return "biome";
@@ -1959,6 +1955,15 @@ var gitTool = {
1959
1955
  },
1960
1956
  async execute(input, ctx, opts) {
1961
1957
  if (!input?.command) throw new Error("git: command is required");
1958
+ if (input.command === "commit" && !input.message) {
1959
+ return {
1960
+ command: "commit",
1961
+ stdout: "",
1962
+ stderr: "git commit requires a message (-m flag)",
1963
+ exitCode: 1,
1964
+ truncated: false
1965
+ };
1966
+ }
1962
1967
  const gitDir = findGitDir2(ctx.cwd, ctx.projectRoot);
1963
1968
  if (!gitDir) {
1964
1969
  return {
@@ -1978,8 +1983,8 @@ function findGitDir2(cwd, projectRoot) {
1978
1983
  let dir = cwd;
1979
1984
  for (let i = 0; i < 20; i++) {
1980
1985
  try {
1981
- const stat9 = statSync(`${dir}/.git`);
1982
- if (stat9.isDirectory()) return dir;
1986
+ const stat10 = statSync(`${dir}/.git`);
1987
+ if (stat10.isDirectory()) return dir;
1983
1988
  } catch {
1984
1989
  }
1985
1990
  if (dir === root) break;
@@ -2418,8 +2423,8 @@ async function runNative(input, base, mode, limit, signal) {
2418
2423
  if (globRe && !globRe.test(e.name) && !globRe.test(full)) continue;
2419
2424
  if (globRe) globRe.lastIndex = 0;
2420
2425
  try {
2421
- const stat9 = await fs9.stat(full);
2422
- if (stat9.size > 1e6) continue;
2426
+ const stat10 = await fs9.stat(full);
2427
+ if (stat10.size > 1e6) continue;
2423
2428
  const head = await fs9.readFile(full);
2424
2429
  if (isBinaryBuffer(head)) continue;
2425
2430
  const text = head.toString("utf8");
@@ -2558,13 +2563,13 @@ var installTool = {
2558
2563
  }
2559
2564
  };
2560
2565
  async function detectPackageManager(cwd) {
2561
- const { stat: stat9 } = await import('fs/promises');
2566
+ const { stat: stat10 } = await import('fs/promises');
2562
2567
  try {
2563
- await stat9(`${cwd}/pnpm-lock.yaml`);
2568
+ await stat10(`${cwd}/pnpm-lock.yaml`);
2564
2569
  return "pnpm";
2565
2570
  } catch {
2566
2571
  try {
2567
- await stat9(`${cwd}/yarn.lock`);
2572
+ await stat10(`${cwd}/yarn.lock`);
2568
2573
  return "yarn";
2569
2574
  } catch {
2570
2575
  return "npm";
@@ -2771,11 +2776,11 @@ var lintTool = {
2771
2776
  }
2772
2777
  };
2773
2778
  async function detectLinter(cwd) {
2774
- const { stat: stat9 } = await import('fs/promises');
2779
+ const { stat: stat10 } = await import('fs/promises');
2775
2780
  const checks = ["biome.json", ".eslintrc.json", "tslint.json", ".eslintrc.js", "tsconfig.json"];
2776
2781
  for (const f of checks) {
2777
2782
  try {
2778
- await stat9(`${cwd}/${f}`);
2783
+ await stat10(`${cwd}/${f}`);
2779
2784
  if (f.includes("biome")) return "biome";
2780
2785
  if (f.includes("eslint")) return "eslint";
2781
2786
  if (f.includes("tslint")) return "tslint";
@@ -3008,14 +3013,13 @@ var outdatedTool = {
3008
3013
  }
3009
3014
  };
3010
3015
  async function detectManager2(cwd) {
3011
- const { stat: stat9 } = __require("fs/promises");
3012
3016
  try {
3013
- await stat9(`${cwd}/pnpm-lock.yaml`);
3017
+ await stat(`${cwd}/pnpm-lock.yaml`);
3014
3018
  return "pnpm";
3015
3019
  } catch {
3016
3020
  }
3017
3021
  try {
3018
- await stat9(`${cwd}/yarn.lock`);
3022
+ await stat(`${cwd}/yarn.lock`);
3019
3023
  return "yarn";
3020
3024
  } catch {
3021
3025
  }
@@ -3351,17 +3355,17 @@ var readTool = {
3351
3355
  async execute(input, ctx) {
3352
3356
  if (!input?.path) throw new Error("read: path is required");
3353
3357
  const absPath = safeResolve(input.path, ctx);
3354
- let stat9;
3358
+ let stat10;
3355
3359
  try {
3356
- stat9 = await fs9.stat(absPath);
3360
+ stat10 = await fs9.stat(absPath);
3357
3361
  } catch (err) {
3358
3362
  const code = err.code;
3359
3363
  if (code === "ENOENT") throw new Error(`read: file not found "${input.path}"`);
3360
3364
  throw new Error(`read: failed to stat "${input.path}": ${err instanceof Error ? err.message : String(err)}`);
3361
3365
  }
3362
- if (!stat9.isFile()) throw new Error(`read: "${input.path}" is not a regular file`);
3363
- if (stat9.size > MAX_BYTES2) {
3364
- throw new Error(`read: file too large (${stat9.size} bytes, limit ${MAX_BYTES2})`);
3366
+ if (!stat10.isFile()) throw new Error(`read: "${input.path}" is not a regular file`);
3367
+ if (stat10.size > MAX_BYTES2) {
3368
+ throw new Error(`read: file too large (${stat10.size} bytes, limit ${MAX_BYTES2})`);
3365
3369
  }
3366
3370
  const buf = await fs9.readFile(absPath);
3367
3371
  if (isBinaryBuffer(buf)) {
@@ -3373,14 +3377,14 @@ var readTool = {
3373
3377
  const offset = Math.max(1, input.offset ?? 1);
3374
3378
  const limit = Math.max(0, Math.min(input.limit ?? 2e3, 5e3));
3375
3379
  if (limit === 0) {
3376
- ctx.recordRead(absPath, stat9.mtimeMs);
3380
+ ctx.recordRead(absPath, stat10.mtimeMs);
3377
3381
  return { text: "", total_lines: total, encoding: "utf8", truncated: total > 0 };
3378
3382
  }
3379
3383
  const slice = allLines.slice(offset - 1, offset - 1 + limit);
3380
3384
  const truncated = offset - 1 + slice.length < total;
3381
3385
  const width = String(offset + slice.length - 1).length;
3382
3386
  const numbered = slice.map((line, i) => `${String(offset + i).padStart(width, " ")}\u2192${line}`).join("\n");
3383
- ctx.recordRead(absPath, stat9.mtimeMs);
3387
+ ctx.recordRead(absPath, stat10.mtimeMs);
3384
3388
  return {
3385
3389
  text: numbered,
3386
3390
  total_lines: total,
@@ -3447,8 +3451,8 @@ var replaceTool = {
3447
3451
  }
3448
3452
  const rel = path.relative(ctx.projectRoot, realPath);
3449
3453
  if (rel.startsWith("..") || path.isAbsolute(rel)) continue;
3450
- const stat9 = await fs9.stat(realPath).catch(() => null);
3451
- if (!stat9 || !stat9.isFile()) continue;
3454
+ const stat10 = await fs9.stat(realPath).catch(() => null);
3455
+ if (!stat10 || !stat10.isFile()) continue;
3452
3456
  let content;
3453
3457
  try {
3454
3458
  const buf = await fs9.readFile(realPath);
@@ -3473,7 +3477,7 @@ var replaceTool = {
3473
3477
  totalReplacements += count;
3474
3478
  if (!dryRun) {
3475
3479
  const newContent = toStyle(newContentLf, style);
3476
- await atomicWrite(realPath, newContent, { mode: stat9.mode & 511 });
3480
+ await atomicWrite(realPath, newContent, { mode: stat10.mode & 511 });
3477
3481
  }
3478
3482
  const diff = dryRun || matches.length > 0 ? unifiedDiff(content, toStyle(newContentLf, style), {
3479
3483
  fromFile: absPath,
@@ -3503,8 +3507,8 @@ async function resolveFiles2(filesInput, ctx, extraGlob) {
3503
3507
  const resolved = [];
3504
3508
  for (const p of parts) {
3505
3509
  const absPath = safeResolve(p, ctx);
3506
- const stat9 = await fs9.stat(absPath).catch(() => null);
3507
- if (stat9?.isFile()) {
3510
+ const stat10 = await fs9.stat(absPath).catch(() => null);
3511
+ if (stat10?.isFile()) {
3508
3512
  resolved.push(absPath);
3509
3513
  }
3510
3514
  }
@@ -3563,8 +3567,8 @@ async function globNative(pattern, base, extraGlob) {
3563
3567
  if (DEFAULT_IGNORE3.includes(e.name)) continue;
3564
3568
  const full = path.join(dir, e.name);
3565
3569
  try {
3566
- const stat9 = await fs9.lstat(full);
3567
- if (stat9.isSymbolicLink()) continue;
3570
+ const stat10 = await fs9.lstat(full);
3571
+ if (stat10.isSymbolicLink()) continue;
3568
3572
  } catch {
3569
3573
  continue;
3570
3574
  }
@@ -4050,11 +4054,11 @@ var testTool = {
4050
4054
  }
4051
4055
  };
4052
4056
  async function detectRunner(cwd) {
4053
- const { stat: stat9 } = await import('fs/promises');
4057
+ const { stat: stat10 } = await import('fs/promises');
4054
4058
  const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
4055
4059
  for (const f of candidates) {
4056
4060
  try {
4057
- await stat9(path.join(cwd, f));
4061
+ await stat10(path.join(cwd, f));
4058
4062
  if (f.includes("vitest")) return "vitest";
4059
4063
  if (f.includes("jest")) return "jest";
4060
4064
  if (f.includes("mocha")) return "mocha";
@@ -4673,11 +4677,11 @@ var typecheckTool = {
4673
4677
  }
4674
4678
  };
4675
4679
  async function findTsConfig(cwd) {
4676
- const { stat: stat9 } = await import('fs/promises');
4680
+ const { stat: stat10 } = await import('fs/promises');
4677
4681
  const candidates = ["tsconfig.json", "tsconfig.base.json"];
4678
4682
  for (const f of candidates) {
4679
4683
  try {
4680
- const s = await stat9(path.join(cwd, f));
4684
+ const s = await stat10(path.join(cwd, f));
4681
4685
  if (s.isFile()) return path.join(cwd, f);
4682
4686
  } catch {
4683
4687
  }
@@ -4707,12 +4711,12 @@ var writeTool = {
4707
4711
  let existed = false;
4708
4712
  let prev = "";
4709
4713
  try {
4710
- const stat10 = await fs9.stat(absPath);
4711
- existed = stat10.isFile();
4714
+ const stat11 = await fs9.stat(absPath);
4715
+ existed = stat11.isFile();
4712
4716
  if (existed) {
4713
4717
  if (!ctx.hasRead(absPath)) {
4714
4718
  prev = await fs9.readFile(absPath, "utf8");
4715
- ctx.recordRead(absPath, stat10.mtimeMs);
4719
+ ctx.recordRead(absPath, stat11.mtimeMs);
4716
4720
  } else {
4717
4721
  prev = await fs9.readFile(absPath, "utf8");
4718
4722
  }
@@ -4725,8 +4729,8 @@ var writeTool = {
4725
4729
  await atomicWrite(absPath, input.content);
4726
4730
  const diff = existed ? unifiedDiff(prev, input.content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
4727
4731
  + (new file, ${input.content.split("\n").length} lines)`;
4728
- const stat9 = await fs9.stat(absPath);
4729
- ctx.recordRead(absPath, stat9.mtimeMs);
4732
+ const stat10 = await fs9.stat(absPath);
4733
+ ctx.recordRead(absPath, stat10.mtimeMs);
4730
4734
  ctx.session.recordFileChange({
4731
4735
  path: absPath,
4732
4736
  action: existed ? "modified" : "created",