reasonix 0.22.0 → 0.23.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/index.js CHANGED
@@ -477,10 +477,10 @@ function globalSettingsPath(homeDirOverride) {
477
477
  function projectSettingsPath(projectRoot) {
478
478
  return join(projectRoot, HOOK_SETTINGS_DIRNAME, HOOK_SETTINGS_FILENAME);
479
479
  }
480
- function readSettingsFile(path) {
481
- if (!existsSync(path)) return null;
480
+ function readSettingsFile(path2) {
481
+ if (!existsSync(path2)) return null;
482
482
  try {
483
- const raw = readFileSync(path, "utf8");
483
+ const raw = readFileSync(path2, "utf8");
484
484
  const parsed = JSON.parse(raw);
485
485
  if (parsed && typeof parsed === "object") return parsed;
486
486
  } catch {
@@ -890,14 +890,14 @@ function collect(prefix, schema, out, required, isRootRequired) {
890
890
  out[prefix] = schema;
891
891
  if (isRootRequired) required.push(prefix);
892
892
  }
893
- function setByPath(target, path, value) {
893
+ function setByPath(target, path2, value) {
894
894
  let cur = target;
895
- for (let i = 0; i < path.length - 1; i++) {
896
- const key = path[i];
895
+ for (let i = 0; i < path2.length - 1; i++) {
896
+ const key = path2[i];
897
897
  if (typeof cur[key] !== "object" || cur[key] === null) cur[key] = {};
898
898
  cur = cur[key];
899
899
  }
900
- cur[path[path.length - 1]] = value;
900
+ cur[path2[path2.length - 1]] = value;
901
901
  }
902
902
 
903
903
  // src/tools.ts
@@ -1311,10 +1311,10 @@ function sanitizeName(name) {
1311
1311
  return cleaned || "default";
1312
1312
  }
1313
1313
  function loadSessionMessages(name) {
1314
- const path = sessionPath(name);
1315
- if (!existsSync3(path)) return [];
1314
+ const path2 = sessionPath(name);
1315
+ if (!existsSync3(path2)) return [];
1316
1316
  try {
1317
- const raw = readFileSync3(path, "utf8");
1317
+ const raw = readFileSync3(path2, "utf8");
1318
1318
  const out = [];
1319
1319
  for (const line of raw.split(/\r?\n/)) {
1320
1320
  const trimmed = line.trim();
@@ -1331,12 +1331,12 @@ function loadSessionMessages(name) {
1331
1331
  }
1332
1332
  }
1333
1333
  function appendSessionMessage(name, message) {
1334
- const path = sessionPath(name);
1335
- mkdirSync(dirname2(path), { recursive: true });
1336
- appendFileSync(path, `${JSON.stringify(message)}
1334
+ const path2 = sessionPath(name);
1335
+ mkdirSync(dirname2(path2), { recursive: true });
1336
+ appendFileSync(path2, `${JSON.stringify(message)}
1337
1337
  `, "utf8");
1338
1338
  try {
1339
- chmodSync(path, 384);
1339
+ chmodSync(path2, 384);
1340
1340
  } catch {
1341
1341
  }
1342
1342
  }
@@ -1348,13 +1348,13 @@ function listSessions() {
1348
1348
  (f) => f.endsWith(".jsonl") && !f.endsWith(".events.jsonl")
1349
1349
  );
1350
1350
  return files.map((file) => {
1351
- const path = join3(dir, file);
1352
- const stat2 = statSync(path);
1351
+ const path2 = join3(dir, file);
1352
+ const stat2 = statSync(path2);
1353
1353
  const name = file.replace(/\.jsonl$/, "");
1354
- const messageCount = countLines(path);
1354
+ const messageCount = countLines(path2);
1355
1355
  return {
1356
1356
  name,
1357
- path,
1357
+ path: path2,
1358
1358
  size: stat2.size,
1359
1359
  messageCount,
1360
1360
  mtime: stat2.mtime,
@@ -1379,11 +1379,11 @@ function loadSessionMeta(name) {
1379
1379
  }
1380
1380
  }
1381
1381
  function deleteSession(name) {
1382
- const path = sessionPath(name);
1382
+ const path2 = sessionPath(name);
1383
1383
  try {
1384
- unlinkSync(path);
1384
+ unlinkSync(path2);
1385
1385
  for (const ext of [".events.jsonl", ".pending.json", ".meta.json", ".plan.json"]) {
1386
- const sidecar = path.replace(/\.jsonl$/, ext);
1386
+ const sidecar = path2.replace(/\.jsonl$/, ext);
1387
1387
  try {
1388
1388
  unlinkSync(sidecar);
1389
1389
  } catch {
@@ -1395,19 +1395,19 @@ function deleteSession(name) {
1395
1395
  }
1396
1396
  }
1397
1397
  function rewriteSession(name, messages) {
1398
- const path = sessionPath(name);
1399
- mkdirSync(dirname2(path), { recursive: true });
1398
+ const path2 = sessionPath(name);
1399
+ mkdirSync(dirname2(path2), { recursive: true });
1400
1400
  const body = messages.map((m) => JSON.stringify(m)).join("\n");
1401
- writeFileSync(path, body ? `${body}
1401
+ writeFileSync(path2, body ? `${body}
1402
1402
  ` : "", "utf8");
1403
1403
  try {
1404
- chmodSync(path, 384);
1404
+ chmodSync(path2, 384);
1405
1405
  } catch {
1406
1406
  }
1407
1407
  }
1408
- function countLines(path) {
1408
+ function countLines(path2) {
1409
1409
  try {
1410
- const raw = readFileSync3(path, "utf8");
1410
+ const raw = readFileSync3(path2, "utf8");
1411
1411
  return raw.split(/\r?\n/).filter((l) => l.trim()).length;
1412
1412
  } catch {
1413
1413
  return 0;
@@ -2982,9 +2982,39 @@ function extractDeepSeekErrorMessage(body) {
2982
2982
  }
2983
2983
 
2984
2984
  // src/at-mentions.ts
2985
- import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2985
+ import { existsSync as existsSync4, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2986
2986
  import { readdir, stat } from "fs/promises";
2987
2987
  import { isAbsolute, join as join4, relative, resolve } from "path";
2988
+
2989
+ // src/gitignore.ts
2990
+ import { readFileSync as readFileSync4 } from "fs";
2991
+ import { readFile } from "fs/promises";
2992
+ import path from "path";
2993
+ import ignore from "ignore";
2994
+ async function loadGitignoreAt(dirAbs) {
2995
+ try {
2996
+ return ignore().add(await readFile(path.join(dirAbs, ".gitignore"), "utf8"));
2997
+ } catch {
2998
+ return null;
2999
+ }
3000
+ }
3001
+ function loadGitignoreAtSync(dirAbs) {
3002
+ try {
3003
+ return ignore().add(readFileSync4(path.join(dirAbs, ".gitignore"), "utf8"));
3004
+ } catch {
3005
+ return null;
3006
+ }
3007
+ }
3008
+ function ignoredByLayers(layers, abs, isDir) {
3009
+ for (const layer of layers) {
3010
+ const rel = path.relative(layer.dirAbs, abs).split(path.sep).join("/");
3011
+ if (!rel || rel.startsWith("..")) continue;
3012
+ if (layer.ig.ignores(isDir ? `${rel}/` : rel)) return true;
3013
+ }
3014
+ return false;
3015
+ }
3016
+
3017
+ // src/at-mentions.ts
2988
3018
  var DEFAULT_AT_MENTION_MAX_BYTES = 64 * 1024;
2989
3019
  var DEFAULT_PICKER_IGNORE_DIRS = [
2990
3020
  "node_modules",
@@ -3006,12 +3036,18 @@ function listFilesSync(root, opts = {}) {
3006
3036
  return listFilesWithStatsSync(root, opts).map((e) => e.path);
3007
3037
  }
3008
3038
  function listFilesWithStatsSync(root, opts = {}) {
3009
- const maxResults = Math.max(1, opts.maxResults ?? 500);
3010
- const ignore = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
3039
+ const maxResults = Math.max(1, opts.maxResults ?? 2e3);
3040
+ const ignoreDirs = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
3011
3041
  const rootAbs = resolve(root);
3042
+ const respectGi = opts.respectGitignore !== false;
3012
3043
  const out = [];
3013
- const walk2 = (dirAbs, dirRel) => {
3044
+ const walk2 = (dirAbs, dirRel, layers) => {
3014
3045
  if (out.length >= maxResults) return;
3046
+ let effectiveLayers = layers;
3047
+ if (respectGi) {
3048
+ const ig = loadGitignoreAtSync(dirAbs);
3049
+ if (ig) effectiveLayers = [...layers, { dirAbs, ig }];
3050
+ }
3015
3051
  let entries;
3016
3052
  try {
3017
3053
  entries = readdirSync2(dirAbs, { withFileTypes: true });
@@ -3022,29 +3058,38 @@ function listFilesWithStatsSync(root, opts = {}) {
3022
3058
  for (const ent of entries) {
3023
3059
  if (out.length >= maxResults) return;
3024
3060
  const relPath = dirRel ? `${dirRel}/${ent.name}` : ent.name;
3061
+ const absPath = join4(dirAbs, ent.name);
3025
3062
  if (ent.isDirectory()) {
3026
- if (ent.name.startsWith(".") || ignore.has(ent.name)) continue;
3027
- walk2(join4(dirAbs, ent.name), relPath);
3063
+ if (ent.name.startsWith(".") || ignoreDirs.has(ent.name)) continue;
3064
+ if (ignoredByLayers(effectiveLayers, absPath, true)) continue;
3065
+ walk2(absPath, relPath, effectiveLayers);
3028
3066
  } else if (ent.isFile()) {
3067
+ if (ignoredByLayers(effectiveLayers, absPath, false)) continue;
3029
3068
  let mtimeMs = 0;
3030
3069
  try {
3031
- mtimeMs = statSync2(join4(dirAbs, ent.name)).mtimeMs;
3070
+ mtimeMs = statSync2(absPath).mtimeMs;
3032
3071
  } catch {
3033
3072
  }
3034
3073
  out.push({ path: relPath, mtimeMs });
3035
3074
  }
3036
3075
  }
3037
3076
  };
3038
- walk2(rootAbs, "");
3077
+ walk2(rootAbs, "", []);
3039
3078
  return out;
3040
3079
  }
3041
3080
  async function listFilesWithStatsAsync(root, opts = {}) {
3042
- const maxResults = Math.max(1, opts.maxResults ?? 500);
3043
- const ignore = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
3081
+ const maxResults = Math.max(1, opts.maxResults ?? 2e3);
3082
+ const ignoreDirs = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
3044
3083
  const rootAbs = resolve(root);
3084
+ const respectGi = opts.respectGitignore !== false;
3045
3085
  const out = [];
3046
- const walk2 = async (dirAbs, dirRel) => {
3086
+ const walk2 = async (dirAbs, dirRel, layers) => {
3047
3087
  if (out.length >= maxResults) return;
3088
+ let effectiveLayers = layers;
3089
+ if (respectGi) {
3090
+ const ig = await loadGitignoreAt(dirAbs);
3091
+ if (ig) effectiveLayers = [...layers, { dirAbs, ig }];
3092
+ }
3048
3093
  let entries;
3049
3094
  try {
3050
3095
  entries = await readdir(dirAbs, { withFileTypes: true });
@@ -3055,35 +3100,42 @@ async function listFilesWithStatsAsync(root, opts = {}) {
3055
3100
  const fileEnts = [];
3056
3101
  for (const ent of entries) {
3057
3102
  if (out.length >= maxResults) break;
3103
+ const relPath = dirRel ? `${dirRel}/${ent.name}` : ent.name;
3104
+ const absPath = join4(dirAbs, ent.name);
3058
3105
  if (ent.isDirectory()) {
3059
- if (ent.name.startsWith(".") || ignore.has(ent.name)) continue;
3106
+ if (ent.name.startsWith(".") || ignoreDirs.has(ent.name)) continue;
3107
+ if (ignoredByLayers(effectiveLayers, absPath, true)) continue;
3060
3108
  if (fileEnts.length > 0) {
3061
- await statBatch(fileEnts, dirAbs, dirRel, out, maxResults);
3109
+ await statBatch(fileEnts, dirAbs, dirRel, out, maxResults, effectiveLayers);
3062
3110
  fileEnts.length = 0;
3063
3111
  if (out.length >= maxResults) return;
3064
3112
  }
3065
- await walk2(join4(dirAbs, ent.name), dirRel ? `${dirRel}/${ent.name}` : ent.name);
3113
+ await walk2(absPath, relPath, effectiveLayers);
3066
3114
  } else if (ent.isFile()) {
3067
3115
  fileEnts.push(ent);
3068
3116
  }
3069
3117
  }
3070
3118
  if (fileEnts.length > 0 && out.length < maxResults) {
3071
- await statBatch(fileEnts, dirAbs, dirRel, out, maxResults);
3119
+ await statBatch(fileEnts, dirAbs, dirRel, out, maxResults, effectiveLayers);
3072
3120
  }
3073
3121
  };
3074
- await walk2(rootAbs, "");
3122
+ await walk2(rootAbs, "", []);
3075
3123
  return out;
3076
3124
  }
3077
- async function statBatch(ents, dirAbs, dirRel, out, maxResults) {
3078
- const remaining = Math.max(0, maxResults - out.length);
3079
- const batch = ents.slice(0, remaining);
3125
+ async function statBatch(ents, dirAbs, dirRel, out, maxResults, layers) {
3126
+ const accepted = [];
3127
+ for (const e of ents) {
3128
+ if (out.length + accepted.length >= maxResults) break;
3129
+ if (ignoredByLayers(layers, join4(dirAbs, e.name), false)) continue;
3130
+ accepted.push(e);
3131
+ }
3080
3132
  const stats = await Promise.all(
3081
- batch.map(
3133
+ accepted.map(
3082
3134
  (e) => stat(join4(dirAbs, e.name)).then((s) => s.mtimeMs).catch(() => 0)
3083
3135
  )
3084
3136
  );
3085
- for (let i = 0; i < batch.length; i++) {
3086
- const ent = batch[i];
3137
+ for (let i = 0; i < accepted.length; i++) {
3138
+ const ent = accepted[i];
3087
3139
  out.push({
3088
3140
  path: dirRel ? `${dirRel}/${ent.name}` : ent.name,
3089
3141
  mtimeMs: stats[i] ?? 0
@@ -3224,20 +3276,20 @@ var defaultFs = {
3224
3276
  return 0;
3225
3277
  }
3226
3278
  },
3227
- read: (p) => readFileSync4(p, "utf8")
3279
+ read: (p) => readFileSync5(p, "utf8")
3228
3280
  };
3229
3281
 
3230
3282
  // src/memory/project.ts
3231
- import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3283
+ import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
3232
3284
  import { join as join5 } from "path";
3233
3285
  var PROJECT_MEMORY_FILE = "REASONIX.md";
3234
3286
  var PROJECT_MEMORY_MAX_CHARS = 8e3;
3235
3287
  function readProjectMemory(rootDir) {
3236
- const path = join5(rootDir, PROJECT_MEMORY_FILE);
3237
- if (!existsSync5(path)) return null;
3288
+ const path2 = join5(rootDir, PROJECT_MEMORY_FILE);
3289
+ if (!existsSync5(path2)) return null;
3238
3290
  let raw;
3239
3291
  try {
3240
- raw = readFileSync5(path, "utf8");
3292
+ raw = readFileSync6(path2, "utf8");
3241
3293
  } catch {
3242
3294
  return null;
3243
3295
  }
@@ -3247,7 +3299,7 @@ function readProjectMemory(rootDir) {
3247
3299
  const truncated = originalChars > PROJECT_MEMORY_MAX_CHARS;
3248
3300
  const content = truncated ? `${trimmed.slice(0, PROJECT_MEMORY_MAX_CHARS)}
3249
3301
  \u2026 (truncated ${originalChars - PROJECT_MEMORY_MAX_CHARS} chars)` : trimmed;
3250
- return { path, content, originalChars, truncated };
3302
+ return { path: path2, content, originalChars, truncated };
3251
3303
  }
3252
3304
  function memoryEnabled() {
3253
3305
  const env = process.env.REASONIX_MEMORY;
@@ -3275,7 +3327,7 @@ import { createHash as createHash2 } from "crypto";
3275
3327
  import {
3276
3328
  existsSync as existsSync7,
3277
3329
  mkdirSync as mkdirSync2,
3278
- readFileSync as readFileSync7,
3330
+ readFileSync as readFileSync8,
3279
3331
  readdirSync as readdirSync4,
3280
3332
  unlinkSync as unlinkSync2,
3281
3333
  writeFileSync as writeFileSync2
@@ -3284,7 +3336,7 @@ import { homedir as homedir4 } from "os";
3284
3336
  import { join as join7, resolve as resolve3 } from "path";
3285
3337
 
3286
3338
  // src/skills.ts
3287
- import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
3339
+ import { existsSync as existsSync6, readFileSync as readFileSync7, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
3288
3340
  import { homedir as homedir3 } from "os";
3289
3341
  import { join as join6, resolve as resolve2 } from "path";
3290
3342
 
@@ -3421,10 +3473,10 @@ var SkillStore = class {
3421
3473
  }
3422
3474
  return null;
3423
3475
  }
3424
- parse(path, stem, scope) {
3476
+ parse(path2, stem, scope) {
3425
3477
  let raw;
3426
3478
  try {
3427
- raw = readFileSync6(path, "utf8");
3479
+ raw = readFileSync7(path2, "utf8");
3428
3480
  } catch {
3429
3481
  return null;
3430
3482
  }
@@ -3435,7 +3487,7 @@ var SkillStore = class {
3435
3487
  description: (data.description ?? "").trim(),
3436
3488
  body: body.trim(),
3437
3489
  scope,
3438
- path,
3490
+ path: path2,
3439
3491
  allowedTools: data["allowed-tools"],
3440
3492
  runAs: parseRunAs(data.runAs),
3441
3493
  model: data.model?.startsWith("deepseek-") ? data.model : void 0
@@ -3758,7 +3810,7 @@ var MemoryStore = class {
3758
3810
  if (!existsSync7(file)) return null;
3759
3811
  let raw;
3760
3812
  try {
3761
- raw = readFileSync7(file, "utf8");
3813
+ raw = readFileSync8(file, "utf8");
3762
3814
  } catch {
3763
3815
  return null;
3764
3816
  }
@@ -3776,7 +3828,7 @@ var MemoryStore = class {
3776
3828
  if (!existsSync7(file)) {
3777
3829
  throw new Error(`memory not found: scope=${scope} name=${name}`);
3778
3830
  }
3779
- const raw = readFileSync7(file, "utf8");
3831
+ const raw = readFileSync8(file, "utf8");
3780
3832
  const { data, body } = parseFrontmatter2(raw);
3781
3833
  return {
3782
3834
  name: data.name ?? name,
@@ -3878,11 +3930,11 @@ var MemoryStore = class {
3878
3930
  }
3879
3931
  };
3880
3932
  function readGlobalReasonixMemory(homeDir = join7(homedir4(), ".reasonix")) {
3881
- const path = join7(homeDir, "REASONIX.md");
3882
- if (!existsSync7(path)) return null;
3933
+ const path2 = join7(homeDir, "REASONIX.md");
3934
+ if (!existsSync7(path2)) return null;
3883
3935
  let raw;
3884
3936
  try {
3885
- raw = readFileSync7(path, "utf8");
3937
+ raw = readFileSync8(path2, "utf8");
3886
3938
  } catch {
3887
3939
  return null;
3888
3940
  }
@@ -3892,7 +3944,7 @@ function readGlobalReasonixMemory(homeDir = join7(homedir4(), ".reasonix")) {
3892
3944
  const truncated = originalChars > 8e3;
3893
3945
  const content = truncated ? `${trimmed.slice(0, 8e3)}
3894
3946
  \u2026 (truncated ${originalChars - 8e3} chars)` : trimmed;
3895
- return { path, content, originalChars, truncated };
3947
+ return { path: path2, content, originalChars, truncated };
3896
3948
  }
3897
3949
  function applyGlobalReasonixMemory(basePrompt, homeDir) {
3898
3950
  if (!memoryEnabled()) return basePrompt;
@@ -4613,7 +4665,7 @@ function registerMemoryTools(registry, opts = {}) {
4613
4665
  });
4614
4666
  }
4615
4667
  try {
4616
- const path = store.write({
4668
+ const path2 = store.write({
4617
4669
  name: args.name,
4618
4670
  type: args.type,
4619
4671
  scope: args.scope,
@@ -4626,7 +4678,7 @@ function registerMemoryTools(registry, opts = {}) {
4626
4678
  "",
4627
4679
  "TREAT THIS AS ESTABLISHED FACT for the rest of this session.",
4628
4680
  "The user just told you \u2014 don't re-explore the filesystem to re-derive it.",
4629
- `(Saved to ${path}; pins into the system prompt on next /new or launch.)`
4681
+ `(Saved to ${path2}; pins into the system prompt on next /new or launch.)`
4630
4682
  ].join("\n");
4631
4683
  } catch (err) {
4632
4684
  return JSON.stringify({ error: `remember failed: ${err.message}` });
@@ -6355,12 +6407,12 @@ ${i + 1}. ${r.title}`);
6355
6407
  }
6356
6408
 
6357
6409
  // src/env.ts
6358
- import { readFileSync as readFileSync8 } from "fs";
6410
+ import { readFileSync as readFileSync9 } from "fs";
6359
6411
  import { resolve as resolve7 } from "path";
6360
- function loadDotenv(path = ".env") {
6412
+ function loadDotenv(path2 = ".env") {
6361
6413
  let raw;
6362
6414
  try {
6363
- raw = readFileSync8(resolve7(process.cwd(), path), "utf8");
6415
+ raw = readFileSync9(resolve7(process.cwd(), path2), "utf8");
6364
6416
  } catch {
6365
6417
  return;
6366
6418
  }
@@ -6379,7 +6431,7 @@ function loadDotenv(path = ".env") {
6379
6431
  }
6380
6432
 
6381
6433
  // src/transcript/log.ts
6382
- import { createWriteStream, readFileSync as readFileSync9 } from "fs";
6434
+ import { createWriteStream, readFileSync as readFileSync10 } from "fs";
6383
6435
  function recordFromLoopEvent(ev, extra) {
6384
6436
  const rec = {
6385
6437
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -6424,13 +6476,13 @@ function writeMeta(stream, meta) {
6424
6476
  stream.write(`${JSON.stringify(line)}
6425
6477
  `);
6426
6478
  }
6427
- function openTranscriptFile(path, meta) {
6428
- const stream = createWriteStream(path, { flags: "a" });
6479
+ function openTranscriptFile(path2, meta) {
6480
+ const stream = createWriteStream(path2, { flags: "a" });
6429
6481
  writeMeta(stream, meta);
6430
6482
  return stream;
6431
6483
  }
6432
- function readTranscript(path) {
6433
- const raw = readFileSync9(path, "utf8");
6484
+ function readTranscript(path2) {
6485
+ const raw = readFileSync10(path2, "utf8");
6434
6486
  return parseTranscript(raw);
6435
6487
  }
6436
6488
  function isPlanStateEmptyShape(s) {
@@ -6461,8 +6513,8 @@ function parseTranscript(raw) {
6461
6513
  }
6462
6514
 
6463
6515
  // src/transcript/replay.ts
6464
- function replayFromFile(path) {
6465
- const parsed = readTranscript(path);
6516
+ function replayFromFile(path2) {
6517
+ const parsed = readTranscript(path2);
6466
6518
  return { parsed, stats: computeReplayStats(parsed.records) };
6467
6519
  }
6468
6520
  function computeReplayStats(records) {
@@ -6877,7 +6929,7 @@ function truncate(s, n) {
6877
6929
  }
6878
6930
 
6879
6931
  // src/version.ts
6880
- import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
6932
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
6881
6933
  import { homedir as homedir5 } from "os";
6882
6934
  import { dirname as dirname4, join as join9 } from "path";
6883
6935
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -6890,7 +6942,7 @@ function readPackageVersion() {
6890
6942
  for (let i = 0; i < 6; i++) {
6891
6943
  const p = join9(dir, "package.json");
6892
6944
  if (existsSync9(p)) {
6893
- const pkg = JSON.parse(readFileSync10(p, "utf8"));
6945
+ const pkg = JSON.parse(readFileSync11(p, "utf8"));
6894
6946
  if (pkg?.name === "reasonix" && typeof pkg.version === "string") {
6895
6947
  return pkg.version;
6896
6948
  }
@@ -6909,7 +6961,7 @@ function cachePath(homeDirOverride) {
6909
6961
  }
6910
6962
  function readCache(homeDirOverride) {
6911
6963
  try {
6912
- const raw = readFileSync10(cachePath(homeDirOverride), "utf8");
6964
+ const raw = readFileSync11(cachePath(homeDirOverride), "utf8");
6913
6965
  const parsed = JSON.parse(raw);
6914
6966
  if (parsed && typeof parsed.version === "string" && typeof parsed.checkedAt === "number") {
6915
6967
  return parsed;
@@ -7715,7 +7767,7 @@ async function trySection(load) {
7715
7767
  }
7716
7768
 
7717
7769
  // src/code/edit-blocks.ts
7718
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync11, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
7770
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync12, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
7719
7771
  import { dirname as dirname5, resolve as resolve8 } from "path";
7720
7772
  var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
7721
7773
  function parseEditBlocks(text) {
@@ -7758,7 +7810,7 @@ function applyEditBlock(block, rootDir) {
7758
7810
  writeFileSync4(absTarget, block.replace, "utf8");
7759
7811
  return { path: block.path, status: "created" };
7760
7812
  }
7761
- const content = readFileSync11(absTarget, "utf8");
7813
+ const content = readFileSync12(absTarget, "utf8");
7762
7814
  if (searchEmpty) {
7763
7815
  return {
7764
7816
  path: block.path,
@@ -7797,7 +7849,7 @@ function snapshotBeforeEdits(blocks, rootDir) {
7797
7849
  continue;
7798
7850
  }
7799
7851
  try {
7800
- snapshots.push({ path: b.path, prevContent: readFileSync11(abs, "utf8") });
7852
+ snapshots.push({ path: b.path, prevContent: readFileSync12(abs, "utf8") });
7801
7853
  } catch {
7802
7854
  snapshots.push({ path: b.path, prevContent: null });
7803
7855
  }
@@ -7840,7 +7892,7 @@ function sep() {
7840
7892
  }
7841
7893
 
7842
7894
  // src/code/prompt.ts
7843
- import { existsSync as existsSync11, readFileSync as readFileSync12 } from "fs";
7895
+ import { existsSync as existsSync11, readFileSync as readFileSync13 } from "fs";
7844
7896
  import { join as join10 } from "path";
7845
7897
  var CODE_SYSTEM_PROMPT = `You are Reasonix Code, a coding assistant. You have filesystem tools (read_file, write_file, edit_file, list_directory, directory_tree, search_files, search_content, get_file_info) rooted at the user's working directory, plus run_command / run_background for shell.
7846
7898
 
@@ -8048,7 +8100,7 @@ function codeSystemPrompt(rootDir, opts = {}) {
8048
8100
  if (existsSync11(gitignorePath)) {
8049
8101
  let content;
8050
8102
  try {
8051
- content = readFileSync12(gitignorePath, "utf8");
8103
+ content = readFileSync13(gitignorePath, "utf8");
8052
8104
  } catch {
8053
8105
  }
8054
8106
  if (content !== void 0) {
@@ -8079,37 +8131,37 @@ ${appendParts.join("\n\n")}`;
8079
8131
  }
8080
8132
 
8081
8133
  // src/config.ts
8082
- import { chmodSync as chmodSync2, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "fs";
8134
+ import { chmodSync as chmodSync2, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "fs";
8083
8135
  import { homedir as homedir6 } from "os";
8084
8136
  import { dirname as dirname6, join as join11 } from "path";
8085
8137
  function defaultConfigPath() {
8086
8138
  return join11(homedir6(), ".reasonix", "config.json");
8087
8139
  }
8088
- function readConfig(path = defaultConfigPath()) {
8140
+ function readConfig(path2 = defaultConfigPath()) {
8089
8141
  try {
8090
- const raw = readFileSync13(path, "utf8");
8142
+ const raw = readFileSync14(path2, "utf8");
8091
8143
  const parsed = JSON.parse(raw);
8092
8144
  if (parsed && typeof parsed === "object") return parsed;
8093
8145
  } catch {
8094
8146
  }
8095
8147
  return {};
8096
8148
  }
8097
- function writeConfig(cfg, path = defaultConfigPath()) {
8098
- mkdirSync5(dirname6(path), { recursive: true });
8099
- writeFileSync5(path, JSON.stringify(cfg, null, 2), "utf8");
8149
+ function writeConfig(cfg, path2 = defaultConfigPath()) {
8150
+ mkdirSync5(dirname6(path2), { recursive: true });
8151
+ writeFileSync5(path2, JSON.stringify(cfg, null, 2), "utf8");
8100
8152
  try {
8101
- chmodSync2(path, 384);
8153
+ chmodSync2(path2, 384);
8102
8154
  } catch {
8103
8155
  }
8104
8156
  }
8105
- function loadApiKey(path = defaultConfigPath()) {
8157
+ function loadApiKey(path2 = defaultConfigPath()) {
8106
8158
  if (process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY;
8107
- return readConfig(path).apiKey;
8159
+ return readConfig(path2).apiKey;
8108
8160
  }
8109
- function saveApiKey(key, path = defaultConfigPath()) {
8110
- const cfg = readConfig(path);
8161
+ function saveApiKey(key, path2 = defaultConfigPath()) {
8162
+ const cfg = readConfig(path2);
8111
8163
  cfg.apiKey = key.trim();
8112
- writeConfig(cfg, path);
8164
+ writeConfig(cfg, path2);
8113
8165
  }
8114
8166
  function isPlausibleKey(key) {
8115
8167
  const trimmed = key.trim();
@@ -8126,7 +8178,7 @@ import {
8126
8178
  appendFileSync as appendFileSync2,
8127
8179
  existsSync as existsSync12,
8128
8180
  mkdirSync as mkdirSync6,
8129
- readFileSync as readFileSync14,
8181
+ readFileSync as readFileSync15,
8130
8182
  statSync as statSync5,
8131
8183
  writeFileSync as writeFileSync6
8132
8184
  } from "fs";
@@ -8137,10 +8189,10 @@ function defaultUsageLogPath(homeDirOverride) {
8137
8189
  }
8138
8190
  var USAGE_COMPACTION_THRESHOLD_BYTES = 5 * 1024 * 1024;
8139
8191
  var USAGE_RETENTION_DAYS = 365;
8140
- function compactUsageLogIfLarge(path, now) {
8192
+ function compactUsageLogIfLarge(path2, now) {
8141
8193
  let size;
8142
8194
  try {
8143
- size = statSync5(path).size;
8195
+ size = statSync5(path2).size;
8144
8196
  } catch {
8145
8197
  return;
8146
8198
  }
@@ -8148,7 +8200,7 @@ function compactUsageLogIfLarge(path, now) {
8148
8200
  const cutoff = now - USAGE_RETENTION_DAYS * 24 * 60 * 60 * 1e3;
8149
8201
  let raw;
8150
8202
  try {
8151
- raw = readFileSync14(path, "utf8");
8203
+ raw = readFileSync15(path2, "utf8");
8152
8204
  } catch {
8153
8205
  return;
8154
8206
  }
@@ -8164,7 +8216,7 @@ function compactUsageLogIfLarge(path, now) {
8164
8216
  }
8165
8217
  if (kept.length === lines.filter((l) => l.trim()).length) return;
8166
8218
  try {
8167
- writeFileSync6(path, kept.length > 0 ? `${kept.join("\n")}
8219
+ writeFileSync6(path2, kept.length > 0 ? `${kept.join("\n")}
8168
8220
  ` : "", "utf8");
8169
8221
  } catch {
8170
8222
  }
@@ -8183,21 +8235,21 @@ function appendUsage(input) {
8183
8235
  };
8184
8236
  if (input.kind === "subagent") record.kind = "subagent";
8185
8237
  if (input.subagent) record.subagent = input.subagent;
8186
- const path = input.path ?? defaultUsageLogPath();
8238
+ const path2 = input.path ?? defaultUsageLogPath();
8187
8239
  try {
8188
- mkdirSync6(dirname7(path), { recursive: true });
8189
- appendFileSync2(path, `${JSON.stringify(record)}
8240
+ mkdirSync6(dirname7(path2), { recursive: true });
8241
+ appendFileSync2(path2, `${JSON.stringify(record)}
8190
8242
  `, "utf8");
8191
- compactUsageLogIfLarge(path, record.ts);
8243
+ compactUsageLogIfLarge(path2, record.ts);
8192
8244
  } catch {
8193
8245
  }
8194
8246
  return record;
8195
8247
  }
8196
- function readUsageLog(path = defaultUsageLogPath()) {
8197
- if (!existsSync12(path)) return [];
8248
+ function readUsageLog(path2 = defaultUsageLogPath()) {
8249
+ if (!existsSync12(path2)) return [];
8198
8250
  let raw;
8199
8251
  try {
8200
- raw = readFileSync14(path, "utf8");
8252
+ raw = readFileSync15(path2, "utf8");
8201
8253
  } catch {
8202
8254
  return [];
8203
8255
  }
@@ -8303,10 +8355,10 @@ function aggregateUsage(records, opts = {}) {
8303
8355
  subagents
8304
8356
  };
8305
8357
  }
8306
- function formatLogSize(path = defaultUsageLogPath()) {
8307
- if (!existsSync12(path)) return "";
8358
+ function formatLogSize(path2 = defaultUsageLogPath()) {
8359
+ if (!existsSync12(path2)) return "";
8308
8360
  try {
8309
- const s = statSync5(path);
8361
+ const s = statSync5(path2);
8310
8362
  const bytes = s.size;
8311
8363
  if (bytes < 1024) return `${bytes} B`;
8312
8364
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;