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/cli/index.js +1135 -822
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +165 -113
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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(
|
|
481
|
-
if (!existsSync(
|
|
480
|
+
function readSettingsFile(path2) {
|
|
481
|
+
if (!existsSync(path2)) return null;
|
|
482
482
|
try {
|
|
483
|
-
const raw = readFileSync(
|
|
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,
|
|
893
|
+
function setByPath(target, path2, value) {
|
|
894
894
|
let cur = target;
|
|
895
|
-
for (let i = 0; i <
|
|
896
|
-
const key =
|
|
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[
|
|
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
|
|
1315
|
-
if (!existsSync3(
|
|
1314
|
+
const path2 = sessionPath(name);
|
|
1315
|
+
if (!existsSync3(path2)) return [];
|
|
1316
1316
|
try {
|
|
1317
|
-
const raw = readFileSync3(
|
|
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
|
|
1335
|
-
mkdirSync(dirname2(
|
|
1336
|
-
appendFileSync(
|
|
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(
|
|
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
|
|
1352
|
-
const stat2 = statSync(
|
|
1351
|
+
const path2 = join3(dir, file);
|
|
1352
|
+
const stat2 = statSync(path2);
|
|
1353
1353
|
const name = file.replace(/\.jsonl$/, "");
|
|
1354
|
-
const messageCount = countLines(
|
|
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
|
|
1382
|
+
const path2 = sessionPath(name);
|
|
1383
1383
|
try {
|
|
1384
|
-
unlinkSync(
|
|
1384
|
+
unlinkSync(path2);
|
|
1385
1385
|
for (const ext of [".events.jsonl", ".pending.json", ".meta.json", ".plan.json"]) {
|
|
1386
|
-
const sidecar =
|
|
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
|
|
1399
|
-
mkdirSync(dirname2(
|
|
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(
|
|
1401
|
+
writeFileSync(path2, body ? `${body}
|
|
1402
1402
|
` : "", "utf8");
|
|
1403
1403
|
try {
|
|
1404
|
-
chmodSync(
|
|
1404
|
+
chmodSync(path2, 384);
|
|
1405
1405
|
} catch {
|
|
1406
1406
|
}
|
|
1407
1407
|
}
|
|
1408
|
-
function countLines(
|
|
1408
|
+
function countLines(path2) {
|
|
1409
1409
|
try {
|
|
1410
|
-
const raw = readFileSync3(
|
|
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
|
|
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 ??
|
|
3010
|
-
const
|
|
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(".") ||
|
|
3027
|
-
|
|
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(
|
|
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 ??
|
|
3043
|
-
const
|
|
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(".") ||
|
|
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(
|
|
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
|
|
3079
|
-
const
|
|
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
|
-
|
|
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 <
|
|
3086
|
-
const ent =
|
|
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) =>
|
|
3279
|
+
read: (p) => readFileSync5(p, "utf8")
|
|
3228
3280
|
};
|
|
3229
3281
|
|
|
3230
3282
|
// src/memory/project.ts
|
|
3231
|
-
import { existsSync as existsSync5, readFileSync as
|
|
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
|
|
3237
|
-
if (!existsSync5(
|
|
3288
|
+
const path2 = join5(rootDir, PROJECT_MEMORY_FILE);
|
|
3289
|
+
if (!existsSync5(path2)) return null;
|
|
3238
3290
|
let raw;
|
|
3239
3291
|
try {
|
|
3240
|
-
raw =
|
|
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
|
|
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
|
|
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(
|
|
3476
|
+
parse(path2, stem, scope) {
|
|
3425
3477
|
let raw;
|
|
3426
3478
|
try {
|
|
3427
|
-
raw =
|
|
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 =
|
|
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 =
|
|
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
|
|
3882
|
-
if (!existsSync7(
|
|
3933
|
+
const path2 = join7(homeDir, "REASONIX.md");
|
|
3934
|
+
if (!existsSync7(path2)) return null;
|
|
3883
3935
|
let raw;
|
|
3884
3936
|
try {
|
|
3885
|
-
raw =
|
|
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
|
|
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 ${
|
|
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
|
|
6410
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
6359
6411
|
import { resolve as resolve7 } from "path";
|
|
6360
|
-
function loadDotenv(
|
|
6412
|
+
function loadDotenv(path2 = ".env") {
|
|
6361
6413
|
let raw;
|
|
6362
6414
|
try {
|
|
6363
|
-
raw =
|
|
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
|
|
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(
|
|
6428
|
-
const stream = createWriteStream(
|
|
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(
|
|
6433
|
-
const raw =
|
|
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(
|
|
6465
|
-
const parsed = readTranscript(
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
8140
|
+
function readConfig(path2 = defaultConfigPath()) {
|
|
8089
8141
|
try {
|
|
8090
|
-
const raw =
|
|
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,
|
|
8098
|
-
mkdirSync5(dirname6(
|
|
8099
|
-
writeFileSync5(
|
|
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(
|
|
8153
|
+
chmodSync2(path2, 384);
|
|
8102
8154
|
} catch {
|
|
8103
8155
|
}
|
|
8104
8156
|
}
|
|
8105
|
-
function loadApiKey(
|
|
8157
|
+
function loadApiKey(path2 = defaultConfigPath()) {
|
|
8106
8158
|
if (process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY;
|
|
8107
|
-
return readConfig(
|
|
8159
|
+
return readConfig(path2).apiKey;
|
|
8108
8160
|
}
|
|
8109
|
-
function saveApiKey(key,
|
|
8110
|
-
const cfg = readConfig(
|
|
8161
|
+
function saveApiKey(key, path2 = defaultConfigPath()) {
|
|
8162
|
+
const cfg = readConfig(path2);
|
|
8111
8163
|
cfg.apiKey = key.trim();
|
|
8112
|
-
writeConfig(cfg,
|
|
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
|
|
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(
|
|
8192
|
+
function compactUsageLogIfLarge(path2, now) {
|
|
8141
8193
|
let size;
|
|
8142
8194
|
try {
|
|
8143
|
-
size = statSync5(
|
|
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 =
|
|
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(
|
|
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
|
|
8238
|
+
const path2 = input.path ?? defaultUsageLogPath();
|
|
8187
8239
|
try {
|
|
8188
|
-
mkdirSync6(dirname7(
|
|
8189
|
-
appendFileSync2(
|
|
8240
|
+
mkdirSync6(dirname7(path2), { recursive: true });
|
|
8241
|
+
appendFileSync2(path2, `${JSON.stringify(record)}
|
|
8190
8242
|
`, "utf8");
|
|
8191
|
-
compactUsageLogIfLarge(
|
|
8243
|
+
compactUsageLogIfLarge(path2, record.ts);
|
|
8192
8244
|
} catch {
|
|
8193
8245
|
}
|
|
8194
8246
|
return record;
|
|
8195
8247
|
}
|
|
8196
|
-
function readUsageLog(
|
|
8197
|
-
if (!existsSync12(
|
|
8248
|
+
function readUsageLog(path2 = defaultUsageLogPath()) {
|
|
8249
|
+
if (!existsSync12(path2)) return [];
|
|
8198
8250
|
let raw;
|
|
8199
8251
|
try {
|
|
8200
|
-
raw =
|
|
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(
|
|
8307
|
-
if (!existsSync12(
|
|
8358
|
+
function formatLogSize(path2 = defaultUsageLogPath()) {
|
|
8359
|
+
if (!existsSync12(path2)) return "";
|
|
8308
8360
|
try {
|
|
8309
|
-
const s = statSync5(
|
|
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`;
|