reasonix 0.5.3 → 0.5.6
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 +255 -86
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +107 -1
- package/dist/index.js +258 -102
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,8 +47,8 @@ function computeWait(attempt, initial, cap, retryAfter) {
|
|
|
47
47
|
}
|
|
48
48
|
function sleep(ms, signal) {
|
|
49
49
|
if (ms <= 0) return Promise.resolve();
|
|
50
|
-
return new Promise((
|
|
51
|
-
const timer = setTimeout(
|
|
50
|
+
return new Promise((resolve8, reject) => {
|
|
51
|
+
const timer = setTimeout(resolve8, ms);
|
|
52
52
|
if (signal) {
|
|
53
53
|
const onAbort = () => {
|
|
54
54
|
clearTimeout(timer);
|
|
@@ -520,7 +520,7 @@ function matchesTool(hook, toolName) {
|
|
|
520
520
|
}
|
|
521
521
|
}
|
|
522
522
|
function defaultSpawner(input) {
|
|
523
|
-
return new Promise((
|
|
523
|
+
return new Promise((resolve8) => {
|
|
524
524
|
const child = spawn(input.command, {
|
|
525
525
|
cwd: input.cwd,
|
|
526
526
|
shell: true,
|
|
@@ -547,7 +547,7 @@ function defaultSpawner(input) {
|
|
|
547
547
|
});
|
|
548
548
|
child.once("error", (err) => {
|
|
549
549
|
clearTimeout(timer);
|
|
550
|
-
|
|
550
|
+
resolve8({
|
|
551
551
|
exitCode: null,
|
|
552
552
|
stdout,
|
|
553
553
|
stderr,
|
|
@@ -557,7 +557,7 @@ function defaultSpawner(input) {
|
|
|
557
557
|
});
|
|
558
558
|
child.once("close", (code) => {
|
|
559
559
|
clearTimeout(timer);
|
|
560
|
-
|
|
560
|
+
resolve8({
|
|
561
561
|
exitCode: code,
|
|
562
562
|
stdout: stdout.trim(),
|
|
563
563
|
stderr: stderr.trim(),
|
|
@@ -618,7 +618,7 @@ async function runHooks(opts) {
|
|
|
618
618
|
}
|
|
619
619
|
|
|
620
620
|
// src/tokenizer.ts
|
|
621
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
621
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
622
622
|
import { createRequire } from "module";
|
|
623
623
|
import { dirname, join as join2 } from "path";
|
|
624
624
|
import { fileURLToPath } from "url";
|
|
@@ -646,17 +646,24 @@ function buildByteToChar() {
|
|
|
646
646
|
var cached = null;
|
|
647
647
|
function resolveDataPath() {
|
|
648
648
|
if (process.env.REASONIX_TOKENIZER_PATH) return process.env.REASONIX_TOKENIZER_PATH;
|
|
649
|
+
const candidates = [];
|
|
649
650
|
try {
|
|
650
651
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
651
|
-
|
|
652
|
+
candidates.push(join2(here, "..", "data", "deepseek-tokenizer.json.gz"));
|
|
653
|
+
candidates.push(join2(here, "..", "..", "data", "deepseek-tokenizer.json.gz"));
|
|
652
654
|
} catch {
|
|
655
|
+
}
|
|
656
|
+
try {
|
|
653
657
|
const req = createRequire(import.meta.url);
|
|
654
|
-
|
|
655
|
-
dirname(req.resolve("reasonix/package.json")),
|
|
656
|
-
"data",
|
|
657
|
-
"deepseek-tokenizer.json.gz"
|
|
658
|
+
candidates.push(
|
|
659
|
+
join2(dirname(req.resolve("reasonix/package.json")), "data", "deepseek-tokenizer.json.gz")
|
|
658
660
|
);
|
|
661
|
+
} catch {
|
|
662
|
+
}
|
|
663
|
+
for (const p of candidates) {
|
|
664
|
+
if (existsSync2(p)) return p;
|
|
659
665
|
}
|
|
666
|
+
return candidates[0] ?? join2(process.cwd(), "data", "deepseek-tokenizer.json.gz");
|
|
660
667
|
}
|
|
661
668
|
function loadTokenizer() {
|
|
662
669
|
if (cached) return cached;
|
|
@@ -780,6 +787,25 @@ function encode(text) {
|
|
|
780
787
|
function countTokens(text) {
|
|
781
788
|
return encode(text).length;
|
|
782
789
|
}
|
|
790
|
+
function estimateConversationTokens(messages) {
|
|
791
|
+
let total = 0;
|
|
792
|
+
for (const m of messages) {
|
|
793
|
+
if (typeof m.content === "string" && m.content) {
|
|
794
|
+
total += countTokens(m.content);
|
|
795
|
+
}
|
|
796
|
+
if (m.tool_calls && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
|
|
797
|
+
total += countTokens(JSON.stringify(m.tool_calls));
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return total;
|
|
801
|
+
}
|
|
802
|
+
function estimateRequestTokens(messages, toolSpecs) {
|
|
803
|
+
let total = estimateConversationTokens(messages);
|
|
804
|
+
if (toolSpecs && toolSpecs.length > 0) {
|
|
805
|
+
total += countTokens(JSON.stringify(toolSpecs));
|
|
806
|
+
}
|
|
807
|
+
return total;
|
|
808
|
+
}
|
|
783
809
|
|
|
784
810
|
// src/repair/flatten.ts
|
|
785
811
|
function analyzeSchema(schema) {
|
|
@@ -1467,7 +1493,7 @@ function signature2(call) {
|
|
|
1467
1493
|
import {
|
|
1468
1494
|
appendFileSync,
|
|
1469
1495
|
chmodSync,
|
|
1470
|
-
existsSync as
|
|
1496
|
+
existsSync as existsSync3,
|
|
1471
1497
|
mkdirSync,
|
|
1472
1498
|
readFileSync as readFileSync3,
|
|
1473
1499
|
readdirSync,
|
|
@@ -1489,7 +1515,7 @@ function sanitizeName(name) {
|
|
|
1489
1515
|
}
|
|
1490
1516
|
function loadSessionMessages(name) {
|
|
1491
1517
|
const path = sessionPath(name);
|
|
1492
|
-
if (!
|
|
1518
|
+
if (!existsSync3(path)) return [];
|
|
1493
1519
|
try {
|
|
1494
1520
|
const raw = readFileSync3(path, "utf8");
|
|
1495
1521
|
const out = [];
|
|
@@ -1519,7 +1545,7 @@ function appendSessionMessage(name, message) {
|
|
|
1519
1545
|
}
|
|
1520
1546
|
function listSessions() {
|
|
1521
1547
|
const dir = sessionsDir();
|
|
1522
|
-
if (!
|
|
1548
|
+
if (!existsSync3(dir)) return [];
|
|
1523
1549
|
try {
|
|
1524
1550
|
const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
1525
1551
|
return files.map((file) => {
|
|
@@ -1715,9 +1741,9 @@ var CacheFirstLoop = class {
|
|
|
1715
1741
|
this.sessionName = opts.session ?? null;
|
|
1716
1742
|
if (this.sessionName) {
|
|
1717
1743
|
const prior = loadSessionMessages(this.sessionName);
|
|
1718
|
-
const { messages, healedCount,
|
|
1744
|
+
const { messages, healedCount, tokensSaved } = healLoadedMessagesByTokens(
|
|
1719
1745
|
prior,
|
|
1720
|
-
|
|
1746
|
+
DEFAULT_MAX_RESULT_TOKENS
|
|
1721
1747
|
);
|
|
1722
1748
|
for (const msg of messages) this.log.append(msg);
|
|
1723
1749
|
this.resumedMessageCount = messages.length;
|
|
@@ -1727,7 +1753,7 @@ var CacheFirstLoop = class {
|
|
|
1727
1753
|
} catch {
|
|
1728
1754
|
}
|
|
1729
1755
|
process.stderr.write(
|
|
1730
|
-
`\u25B8 session "${this.sessionName}": healed ${healedCount} entr${healedCount === 1 ? "y" : "ies"}${
|
|
1756
|
+
`\u25B8 session "${this.sessionName}": healed ${healedCount} entr${healedCount === 1 ? "y" : "ies"}${tokensSaved > 0 ? ` (shrunk ${tokensSaved.toLocaleString()} tokens of oversized tool output)` : " (dropped dangling tool_calls tail)"}. Rewrote session file.
|
|
1731
1757
|
`
|
|
1732
1758
|
);
|
|
1733
1759
|
}
|
|
@@ -1923,7 +1949,32 @@ var CacheFirstLoop = class {
|
|
|
1923
1949
|
content: `${iter}/${this.maxToolIters} tool calls used \u2014 approaching budget. Press Esc to force a summary now.`
|
|
1924
1950
|
};
|
|
1925
1951
|
}
|
|
1926
|
-
|
|
1952
|
+
let messages = this.buildMessages(pendingUser);
|
|
1953
|
+
{
|
|
1954
|
+
const ctxMax2 = DEEPSEEK_CONTEXT_TOKENS[this.model] ?? DEFAULT_CONTEXT_TOKENS;
|
|
1955
|
+
const estimate = estimateRequestTokens(messages, this.prefix.toolSpecs);
|
|
1956
|
+
if (estimate / ctxMax2 > 0.95) {
|
|
1957
|
+
const result = this.compact(1e3);
|
|
1958
|
+
if (result.healedCount > 0) {
|
|
1959
|
+
yield {
|
|
1960
|
+
turn: this._turn,
|
|
1961
|
+
role: "warning",
|
|
1962
|
+
content: `preflight: request ~${estimate.toLocaleString()}/${ctxMax2.toLocaleString()} tokens (${Math.round(
|
|
1963
|
+
estimate / ctxMax2 * 100
|
|
1964
|
+
)}%) \u2014 pre-compacted ${result.healedCount} tool result(s), saved ${result.tokensSaved.toLocaleString()} tokens. Sending.`
|
|
1965
|
+
};
|
|
1966
|
+
messages = this.buildMessages(pendingUser);
|
|
1967
|
+
} else {
|
|
1968
|
+
yield {
|
|
1969
|
+
turn: this._turn,
|
|
1970
|
+
role: "warning",
|
|
1971
|
+
content: `preflight: request ~${estimate.toLocaleString()}/${ctxMax2.toLocaleString()} tokens (${Math.round(
|
|
1972
|
+
estimate / ctxMax2 * 100
|
|
1973
|
+
)}%) and nothing to auto-compact \u2014 DeepSeek will likely 400. Run /forget or /clear to start fresh.`
|
|
1974
|
+
};
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1927
1978
|
let assistantContent = "";
|
|
1928
1979
|
let reasoningContent = "";
|
|
1929
1980
|
let toolCalls = [];
|
|
@@ -1971,8 +2022,8 @@ var CacheFirstLoop = class {
|
|
|
1971
2022
|
}
|
|
1972
2023
|
);
|
|
1973
2024
|
for (let k = 0; k < budget; k++) {
|
|
1974
|
-
const sample = queue.shift() ?? await new Promise((
|
|
1975
|
-
waiter =
|
|
2025
|
+
const sample = queue.shift() ?? await new Promise((resolve8) => {
|
|
2026
|
+
waiter = resolve8;
|
|
1976
2027
|
});
|
|
1977
2028
|
yield {
|
|
1978
2029
|
turn: this._turn,
|
|
@@ -2371,15 +2422,12 @@ function shrinkOversizedToolResultsByTokens(messages, maxTokens) {
|
|
|
2371
2422
|
});
|
|
2372
2423
|
return { messages: out, healedCount, tokensSaved, charsSaved };
|
|
2373
2424
|
}
|
|
2374
|
-
function
|
|
2375
|
-
const shrunk = shrinkOversizedToolResults(messages, maxChars);
|
|
2376
|
-
let healedCount = shrunk.healedCount;
|
|
2425
|
+
function fixToolCallPairing(messages) {
|
|
2377
2426
|
const out = [];
|
|
2378
|
-
const openCallIds = /* @__PURE__ */ new Set();
|
|
2379
2427
|
let droppedAssistantCalls = 0;
|
|
2380
2428
|
let droppedStrayTools = 0;
|
|
2381
|
-
for (let i = 0; i <
|
|
2382
|
-
const msg =
|
|
2429
|
+
for (let i = 0; i < messages.length; i++) {
|
|
2430
|
+
const msg = messages[i];
|
|
2383
2431
|
if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) {
|
|
2384
2432
|
const needed = /* @__PURE__ */ new Set();
|
|
2385
2433
|
for (const call of msg.tool_calls) {
|
|
@@ -2387,8 +2435,8 @@ function healLoadedMessages(messages, maxChars) {
|
|
|
2387
2435
|
}
|
|
2388
2436
|
const candidates = [];
|
|
2389
2437
|
let j = i + 1;
|
|
2390
|
-
while (j <
|
|
2391
|
-
const nxt =
|
|
2438
|
+
while (j < messages.length && needed.size > 0) {
|
|
2439
|
+
const nxt = messages[j];
|
|
2392
2440
|
if (nxt.role !== "tool") break;
|
|
2393
2441
|
const id = nxt.tool_call_id ?? "";
|
|
2394
2442
|
if (!needed.has(id)) break;
|
|
@@ -2413,8 +2461,24 @@ function healLoadedMessages(messages, maxChars) {
|
|
|
2413
2461
|
}
|
|
2414
2462
|
out.push(msg);
|
|
2415
2463
|
}
|
|
2416
|
-
|
|
2417
|
-
|
|
2464
|
+
return { messages: out, droppedAssistantCalls, droppedStrayTools };
|
|
2465
|
+
}
|
|
2466
|
+
function healLoadedMessages(messages, maxChars) {
|
|
2467
|
+
const shrunk = shrinkOversizedToolResults(messages, maxChars);
|
|
2468
|
+
const paired = fixToolCallPairing(shrunk.messages);
|
|
2469
|
+
const healedCount = shrunk.healedCount + paired.droppedAssistantCalls + paired.droppedStrayTools;
|
|
2470
|
+
return { messages: paired.messages, healedCount, healedFrom: shrunk.healedFrom };
|
|
2471
|
+
}
|
|
2472
|
+
function healLoadedMessagesByTokens(messages, maxTokens) {
|
|
2473
|
+
const shrunk = shrinkOversizedToolResultsByTokens(messages, maxTokens);
|
|
2474
|
+
const paired = fixToolCallPairing(shrunk.messages);
|
|
2475
|
+
const healedCount = shrunk.healedCount + paired.droppedAssistantCalls + paired.droppedStrayTools;
|
|
2476
|
+
return {
|
|
2477
|
+
messages: paired.messages,
|
|
2478
|
+
healedCount,
|
|
2479
|
+
tokensSaved: shrunk.tokensSaved,
|
|
2480
|
+
charsSaved: shrunk.charsSaved
|
|
2481
|
+
};
|
|
2418
2482
|
}
|
|
2419
2483
|
function formatLoopError(err) {
|
|
2420
2484
|
const msg = err.message ?? "";
|
|
@@ -2426,17 +2490,104 @@ function formatLoopError(err) {
|
|
|
2426
2490
|
return msg;
|
|
2427
2491
|
}
|
|
2428
2492
|
|
|
2493
|
+
// src/at-mentions.ts
|
|
2494
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
2495
|
+
import { isAbsolute, relative, resolve } from "path";
|
|
2496
|
+
var DEFAULT_AT_MENTION_MAX_BYTES = 64 * 1024;
|
|
2497
|
+
var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
|
|
2498
|
+
function expandAtMentions(text, rootDir, opts = {}) {
|
|
2499
|
+
const maxBytes = opts.maxBytes ?? DEFAULT_AT_MENTION_MAX_BYTES;
|
|
2500
|
+
const fs2 = opts.fs ?? defaultFs;
|
|
2501
|
+
const root = resolve(rootDir);
|
|
2502
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2503
|
+
const expansions = [];
|
|
2504
|
+
for (const match of text.matchAll(AT_MENTION_PATTERN)) {
|
|
2505
|
+
const rawPath = match[1] ?? "";
|
|
2506
|
+
const cleaned = rawPath.replace(/\.+$/, "");
|
|
2507
|
+
if (!cleaned) continue;
|
|
2508
|
+
const token = `@${cleaned}`;
|
|
2509
|
+
if (seen.has(token)) continue;
|
|
2510
|
+
const expansion = resolveMention(cleaned, root, maxBytes, fs2);
|
|
2511
|
+
seen.set(token, expansion);
|
|
2512
|
+
expansions.push(expansion);
|
|
2513
|
+
}
|
|
2514
|
+
if (expansions.length === 0) return { text, expansions };
|
|
2515
|
+
const blocks = [];
|
|
2516
|
+
for (const ex of expansions) {
|
|
2517
|
+
if (ex.ok) {
|
|
2518
|
+
const content = readSafe(root, ex.path, fs2);
|
|
2519
|
+
blocks.push(`<file path="${ex.path}">
|
|
2520
|
+
${content}
|
|
2521
|
+
</file>`);
|
|
2522
|
+
} else {
|
|
2523
|
+
blocks.push(`<file path="${ex.path}" skipped="${ex.skip}" />`);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
const augmented = `${text}
|
|
2527
|
+
|
|
2528
|
+
[Referenced files]
|
|
2529
|
+
${blocks.join("\n\n")}`;
|
|
2530
|
+
return { text: augmented, expansions };
|
|
2531
|
+
}
|
|
2532
|
+
function resolveMention(rawPath, root, maxBytes, fs2) {
|
|
2533
|
+
if (isAbsolute(rawPath)) {
|
|
2534
|
+
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "escape" };
|
|
2535
|
+
}
|
|
2536
|
+
const resolved = resolve(root, rawPath);
|
|
2537
|
+
const rel = relative(root, resolved);
|
|
2538
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
2539
|
+
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "escape" };
|
|
2540
|
+
}
|
|
2541
|
+
if (!fs2.exists(resolved)) {
|
|
2542
|
+
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "missing" };
|
|
2543
|
+
}
|
|
2544
|
+
if (!fs2.isFile(resolved)) {
|
|
2545
|
+
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "not-file" };
|
|
2546
|
+
}
|
|
2547
|
+
const size = fs2.size(resolved);
|
|
2548
|
+
if (size > maxBytes) {
|
|
2549
|
+
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "too-large", bytes: size };
|
|
2550
|
+
}
|
|
2551
|
+
return { token: `@${rawPath}`, path: rawPath, ok: true, bytes: size };
|
|
2552
|
+
}
|
|
2553
|
+
function readSafe(root, rawPath, fs2) {
|
|
2554
|
+
const resolved = resolve(root, rawPath);
|
|
2555
|
+
try {
|
|
2556
|
+
return fs2.read(resolved);
|
|
2557
|
+
} catch {
|
|
2558
|
+
return "(read failed)";
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
var defaultFs = {
|
|
2562
|
+
exists: (p) => existsSync4(p),
|
|
2563
|
+
isFile: (p) => {
|
|
2564
|
+
try {
|
|
2565
|
+
return statSync2(p).isFile();
|
|
2566
|
+
} catch {
|
|
2567
|
+
return false;
|
|
2568
|
+
}
|
|
2569
|
+
},
|
|
2570
|
+
size: (p) => {
|
|
2571
|
+
try {
|
|
2572
|
+
return statSync2(p).size;
|
|
2573
|
+
} catch {
|
|
2574
|
+
return 0;
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
read: (p) => readFileSync4(p, "utf8")
|
|
2578
|
+
};
|
|
2579
|
+
|
|
2429
2580
|
// src/project-memory.ts
|
|
2430
|
-
import { existsSync as
|
|
2581
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
2431
2582
|
import { join as join4 } from "path";
|
|
2432
2583
|
var PROJECT_MEMORY_FILE = "REASONIX.md";
|
|
2433
2584
|
var PROJECT_MEMORY_MAX_CHARS = 8e3;
|
|
2434
2585
|
function readProjectMemory(rootDir) {
|
|
2435
2586
|
const path = join4(rootDir, PROJECT_MEMORY_FILE);
|
|
2436
|
-
if (!
|
|
2587
|
+
if (!existsSync5(path)) return null;
|
|
2437
2588
|
let raw;
|
|
2438
2589
|
try {
|
|
2439
|
-
raw =
|
|
2590
|
+
raw = readFileSync5(path, "utf8");
|
|
2440
2591
|
} catch {
|
|
2441
2592
|
return null;
|
|
2442
2593
|
}
|
|
@@ -2472,20 +2623,20 @@ ${mem.content}
|
|
|
2472
2623
|
// src/user-memory.ts
|
|
2473
2624
|
import { createHash as createHash2 } from "crypto";
|
|
2474
2625
|
import {
|
|
2475
|
-
existsSync as
|
|
2626
|
+
existsSync as existsSync7,
|
|
2476
2627
|
mkdirSync as mkdirSync2,
|
|
2477
|
-
readFileSync as
|
|
2628
|
+
readFileSync as readFileSync7,
|
|
2478
2629
|
readdirSync as readdirSync3,
|
|
2479
2630
|
unlinkSync as unlinkSync2,
|
|
2480
2631
|
writeFileSync as writeFileSync2
|
|
2481
2632
|
} from "fs";
|
|
2482
2633
|
import { homedir as homedir4 } from "os";
|
|
2483
|
-
import { join as join6, resolve as
|
|
2634
|
+
import { join as join6, resolve as resolve3 } from "path";
|
|
2484
2635
|
|
|
2485
2636
|
// src/skills.ts
|
|
2486
|
-
import { existsSync as
|
|
2637
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
2487
2638
|
import { homedir as homedir3 } from "os";
|
|
2488
|
-
import { join as join5, resolve } from "path";
|
|
2639
|
+
import { join as join5, resolve as resolve2 } from "path";
|
|
2489
2640
|
var SKILLS_DIRNAME = "skills";
|
|
2490
2641
|
var SKILL_FILE = "SKILL.md";
|
|
2491
2642
|
var SKILLS_INDEX_MAX_CHARS = 4e3;
|
|
@@ -2516,7 +2667,7 @@ var SkillStore = class {
|
|
|
2516
2667
|
disableBuiltins;
|
|
2517
2668
|
constructor(opts = {}) {
|
|
2518
2669
|
this.homeDir = opts.homeDir ?? homedir3();
|
|
2519
|
-
this.projectRoot = opts.projectRoot ?
|
|
2670
|
+
this.projectRoot = opts.projectRoot ? resolve2(opts.projectRoot) : void 0;
|
|
2520
2671
|
this.disableBuiltins = opts.disableBuiltins === true;
|
|
2521
2672
|
}
|
|
2522
2673
|
/** True iff this store was configured with a project root. */
|
|
@@ -2547,7 +2698,7 @@ var SkillStore = class {
|
|
|
2547
2698
|
list() {
|
|
2548
2699
|
const byName = /* @__PURE__ */ new Map();
|
|
2549
2700
|
for (const { dir, scope } of this.roots()) {
|
|
2550
|
-
if (!
|
|
2701
|
+
if (!existsSync6(dir)) continue;
|
|
2551
2702
|
let entries;
|
|
2552
2703
|
try {
|
|
2553
2704
|
entries = readdirSync2(dir, { withFileTypes: true });
|
|
@@ -2571,13 +2722,13 @@ var SkillStore = class {
|
|
|
2571
2722
|
read(name) {
|
|
2572
2723
|
if (!isValidSkillName(name)) return null;
|
|
2573
2724
|
for (const { dir, scope } of this.roots()) {
|
|
2574
|
-
if (!
|
|
2725
|
+
if (!existsSync6(dir)) continue;
|
|
2575
2726
|
const dirCandidate = join5(dir, name, SKILL_FILE);
|
|
2576
|
-
if (
|
|
2727
|
+
if (existsSync6(dirCandidate) && statSync3(dirCandidate).isFile()) {
|
|
2577
2728
|
return this.parse(dirCandidate, name, scope);
|
|
2578
2729
|
}
|
|
2579
2730
|
const flatCandidate = join5(dir, `${name}.md`);
|
|
2580
|
-
if (
|
|
2731
|
+
if (existsSync6(flatCandidate) && statSync3(flatCandidate).isFile()) {
|
|
2581
2732
|
return this.parse(flatCandidate, name, scope);
|
|
2582
2733
|
}
|
|
2583
2734
|
}
|
|
@@ -2592,7 +2743,7 @@ var SkillStore = class {
|
|
|
2592
2743
|
if (entry.isDirectory()) {
|
|
2593
2744
|
if (!isValidSkillName(entry.name)) return null;
|
|
2594
2745
|
const file = join5(dir, entry.name, SKILL_FILE);
|
|
2595
|
-
if (!
|
|
2746
|
+
if (!existsSync6(file)) return null;
|
|
2596
2747
|
return this.parse(file, entry.name, scope);
|
|
2597
2748
|
}
|
|
2598
2749
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -2605,7 +2756,7 @@ var SkillStore = class {
|
|
|
2605
2756
|
parse(path, stem, scope) {
|
|
2606
2757
|
let raw;
|
|
2607
2758
|
try {
|
|
2608
|
-
raw =
|
|
2759
|
+
raw = readFileSync6(path, "utf8");
|
|
2609
2760
|
} catch {
|
|
2610
2761
|
return null;
|
|
2611
2762
|
}
|
|
@@ -2732,7 +2883,7 @@ function sanitizeMemoryName(raw) {
|
|
|
2732
2883
|
return trimmed;
|
|
2733
2884
|
}
|
|
2734
2885
|
function projectHash(rootDir) {
|
|
2735
|
-
const abs =
|
|
2886
|
+
const abs = resolve3(rootDir);
|
|
2736
2887
|
return createHash2("sha1").update(abs).digest("hex").slice(0, 16);
|
|
2737
2888
|
}
|
|
2738
2889
|
function scopeDir(opts) {
|
|
@@ -2745,7 +2896,7 @@ function scopeDir(opts) {
|
|
|
2745
2896
|
return join6(opts.homeDir, USER_MEMORY_DIR, projectHash(opts.projectRoot));
|
|
2746
2897
|
}
|
|
2747
2898
|
function ensureDir(p) {
|
|
2748
|
-
if (!
|
|
2899
|
+
if (!existsSync7(p)) mkdirSync2(p, { recursive: true });
|
|
2749
2900
|
}
|
|
2750
2901
|
function parseFrontmatter2(raw) {
|
|
2751
2902
|
const lines = raw.split(/\r?\n/);
|
|
@@ -2791,7 +2942,7 @@ var MemoryStore = class {
|
|
|
2791
2942
|
projectRoot;
|
|
2792
2943
|
constructor(opts = {}) {
|
|
2793
2944
|
this.homeDir = opts.homeDir ?? join6(homedir4(), ".reasonix");
|
|
2794
|
-
this.projectRoot = opts.projectRoot ?
|
|
2945
|
+
this.projectRoot = opts.projectRoot ? resolve3(opts.projectRoot) : void 0;
|
|
2795
2946
|
}
|
|
2796
2947
|
/** Directory this store writes `scope` files into, creating it if needed. */
|
|
2797
2948
|
dir(scope) {
|
|
@@ -2817,10 +2968,10 @@ var MemoryStore = class {
|
|
|
2817
2968
|
scopeDir({ homeDir: this.homeDir, scope, projectRoot: this.projectRoot }),
|
|
2818
2969
|
MEMORY_INDEX_FILE
|
|
2819
2970
|
);
|
|
2820
|
-
if (!
|
|
2971
|
+
if (!existsSync7(file)) return null;
|
|
2821
2972
|
let raw;
|
|
2822
2973
|
try {
|
|
2823
|
-
raw =
|
|
2974
|
+
raw = readFileSync7(file, "utf8");
|
|
2824
2975
|
} catch {
|
|
2825
2976
|
return null;
|
|
2826
2977
|
}
|
|
@@ -2835,10 +2986,10 @@ var MemoryStore = class {
|
|
|
2835
2986
|
/** Read one memory file's body (frontmatter stripped). Throws if missing. */
|
|
2836
2987
|
read(scope, name) {
|
|
2837
2988
|
const file = this.pathFor(scope, name);
|
|
2838
|
-
if (!
|
|
2989
|
+
if (!existsSync7(file)) {
|
|
2839
2990
|
throw new Error(`memory not found: scope=${scope} name=${name}`);
|
|
2840
2991
|
}
|
|
2841
|
-
const raw =
|
|
2992
|
+
const raw = readFileSync7(file, "utf8");
|
|
2842
2993
|
const { data, body } = parseFrontmatter2(raw);
|
|
2843
2994
|
return {
|
|
2844
2995
|
name: data.name ?? name,
|
|
@@ -2859,7 +3010,7 @@ var MemoryStore = class {
|
|
|
2859
3010
|
const scopes = this.projectRoot ? ["global", "project"] : ["global"];
|
|
2860
3011
|
for (const scope of scopes) {
|
|
2861
3012
|
const dir = scopeDir({ homeDir: this.homeDir, scope, projectRoot: this.projectRoot });
|
|
2862
|
-
if (!
|
|
3013
|
+
if (!existsSync7(dir)) continue;
|
|
2863
3014
|
let entries;
|
|
2864
3015
|
try {
|
|
2865
3016
|
entries = readdirSync3(dir);
|
|
@@ -2913,7 +3064,7 @@ var MemoryStore = class {
|
|
|
2913
3064
|
throw new Error("cannot delete project-scoped memory: no projectRoot configured");
|
|
2914
3065
|
}
|
|
2915
3066
|
const file = this.pathFor(scope, rawName);
|
|
2916
|
-
if (!
|
|
3067
|
+
if (!existsSync7(file)) return false;
|
|
2917
3068
|
unlinkSync2(file);
|
|
2918
3069
|
this.regenerateIndex(scope);
|
|
2919
3070
|
return true;
|
|
@@ -2926,7 +3077,7 @@ var MemoryStore = class {
|
|
|
2926
3077
|
*/
|
|
2927
3078
|
regenerateIndex(scope) {
|
|
2928
3079
|
const dir = scopeDir({ homeDir: this.homeDir, scope, projectRoot: this.projectRoot });
|
|
2929
|
-
if (!
|
|
3080
|
+
if (!existsSync7(dir)) return;
|
|
2930
3081
|
let files;
|
|
2931
3082
|
try {
|
|
2932
3083
|
files = readdirSync3(dir);
|
|
@@ -2936,7 +3087,7 @@ var MemoryStore = class {
|
|
|
2936
3087
|
const mdFiles = files.filter((f) => f !== MEMORY_INDEX_FILE && f.endsWith(".md")).sort((a, b) => a.localeCompare(b));
|
|
2937
3088
|
const indexPath = join6(dir, MEMORY_INDEX_FILE);
|
|
2938
3089
|
if (mdFiles.length === 0) {
|
|
2939
|
-
if (
|
|
3090
|
+
if (existsSync7(indexPath)) unlinkSync2(indexPath);
|
|
2940
3091
|
return;
|
|
2941
3092
|
}
|
|
2942
3093
|
const lines = [];
|
|
@@ -3870,7 +4021,7 @@ function forkRegistryExcluding(parent, exclude) {
|
|
|
3870
4021
|
|
|
3871
4022
|
// src/tools/shell.ts
|
|
3872
4023
|
import { spawn as spawn2 } from "child_process";
|
|
3873
|
-
import { existsSync as
|
|
4024
|
+
import { existsSync as existsSync8, statSync as statSync4 } from "fs";
|
|
3874
4025
|
import * as pathMod2 from "path";
|
|
3875
4026
|
var DEFAULT_TIMEOUT_SEC = 60;
|
|
3876
4027
|
var DEFAULT_MAX_OUTPUT_CHARS = 32e3;
|
|
@@ -4040,7 +4191,7 @@ async function runCommand(cmd, opts) {
|
|
|
4040
4191
|
};
|
|
4041
4192
|
const { bin, args, spawnOverrides } = prepareSpawn(argv);
|
|
4042
4193
|
const effectiveSpawnOpts = { ...spawnOpts, ...spawnOverrides };
|
|
4043
|
-
return await new Promise((
|
|
4194
|
+
return await new Promise((resolve8, reject) => {
|
|
4044
4195
|
let child;
|
|
4045
4196
|
try {
|
|
4046
4197
|
child = spawn2(bin, args, effectiveSpawnOpts);
|
|
@@ -4073,7 +4224,7 @@ async function runCommand(cmd, opts) {
|
|
|
4073
4224
|
const output = buf.length > maxChars ? `${buf.slice(0, maxChars)}
|
|
4074
4225
|
|
|
4075
4226
|
[\u2026 truncated ${buf.length - maxChars} chars \u2026]` : buf;
|
|
4076
|
-
|
|
4227
|
+
resolve8({ exitCode: code, output, timedOut });
|
|
4077
4228
|
});
|
|
4078
4229
|
});
|
|
4079
4230
|
}
|
|
@@ -4098,7 +4249,7 @@ function resolveExecutable(cmd, opts = {}) {
|
|
|
4098
4249
|
}
|
|
4099
4250
|
function defaultIsFile(full) {
|
|
4100
4251
|
try {
|
|
4101
|
-
return
|
|
4252
|
+
return existsSync8(full) && statSync4(full).isFile();
|
|
4102
4253
|
} catch {
|
|
4103
4254
|
return false;
|
|
4104
4255
|
}
|
|
@@ -4425,12 +4576,12 @@ ${i + 1}. ${r.title}`);
|
|
|
4425
4576
|
}
|
|
4426
4577
|
|
|
4427
4578
|
// src/env.ts
|
|
4428
|
-
import { readFileSync as
|
|
4429
|
-
import { resolve as
|
|
4579
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
4580
|
+
import { resolve as resolve6 } from "path";
|
|
4430
4581
|
function loadDotenv(path = ".env") {
|
|
4431
4582
|
let raw;
|
|
4432
4583
|
try {
|
|
4433
|
-
raw =
|
|
4584
|
+
raw = readFileSync8(resolve6(process.cwd(), path), "utf8");
|
|
4434
4585
|
} catch {
|
|
4435
4586
|
return;
|
|
4436
4587
|
}
|
|
@@ -4449,7 +4600,7 @@ function loadDotenv(path = ".env") {
|
|
|
4449
4600
|
}
|
|
4450
4601
|
|
|
4451
4602
|
// src/transcript.ts
|
|
4452
|
-
import { createWriteStream, readFileSync as
|
|
4603
|
+
import { createWriteStream, readFileSync as readFileSync9 } from "fs";
|
|
4453
4604
|
function recordFromLoopEvent(ev, extra) {
|
|
4454
4605
|
const rec = {
|
|
4455
4606
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -4500,7 +4651,7 @@ function openTranscriptFile(path, meta) {
|
|
|
4500
4651
|
return stream;
|
|
4501
4652
|
}
|
|
4502
4653
|
function readTranscript(path) {
|
|
4503
|
-
const raw =
|
|
4654
|
+
const raw = readFileSync9(path, "utf8");
|
|
4504
4655
|
return parseTranscript(raw);
|
|
4505
4656
|
}
|
|
4506
4657
|
function isPlanStateEmptyShape(s) {
|
|
@@ -5112,7 +5263,7 @@ var McpClient = class {
|
|
|
5112
5263
|
const id = this.nextId++;
|
|
5113
5264
|
const frame = { jsonrpc: "2.0", id, method, params };
|
|
5114
5265
|
let abortHandler = null;
|
|
5115
|
-
const promise = new Promise((
|
|
5266
|
+
const promise = new Promise((resolve8, reject) => {
|
|
5116
5267
|
const timeout = setTimeout(() => {
|
|
5117
5268
|
this.pending.delete(id);
|
|
5118
5269
|
if (abortHandler && signal) signal.removeEventListener("abort", abortHandler);
|
|
@@ -5121,7 +5272,7 @@ var McpClient = class {
|
|
|
5121
5272
|
);
|
|
5122
5273
|
}, this.requestTimeoutMs);
|
|
5123
5274
|
this.pending.set(id, {
|
|
5124
|
-
resolve:
|
|
5275
|
+
resolve: resolve8,
|
|
5125
5276
|
reject,
|
|
5126
5277
|
timeout
|
|
5127
5278
|
});
|
|
@@ -5244,12 +5395,12 @@ var StdioTransport = class {
|
|
|
5244
5395
|
}
|
|
5245
5396
|
async send(message) {
|
|
5246
5397
|
if (this.closed) throw new Error("MCP transport is closed");
|
|
5247
|
-
return new Promise((
|
|
5398
|
+
return new Promise((resolve8, reject) => {
|
|
5248
5399
|
const line = `${JSON.stringify(message)}
|
|
5249
5400
|
`;
|
|
5250
5401
|
this.child.stdin.write(line, "utf8", (err) => {
|
|
5251
5402
|
if (err) reject(err);
|
|
5252
|
-
else
|
|
5403
|
+
else resolve8();
|
|
5253
5404
|
});
|
|
5254
5405
|
});
|
|
5255
5406
|
}
|
|
@@ -5260,8 +5411,8 @@ var StdioTransport = class {
|
|
|
5260
5411
|
continue;
|
|
5261
5412
|
}
|
|
5262
5413
|
if (this.closed) return;
|
|
5263
|
-
const next = await new Promise((
|
|
5264
|
-
this.waiters.push(
|
|
5414
|
+
const next = await new Promise((resolve8) => {
|
|
5415
|
+
this.waiters.push(resolve8);
|
|
5265
5416
|
});
|
|
5266
5417
|
if (next === null) return;
|
|
5267
5418
|
yield next;
|
|
@@ -5327,8 +5478,8 @@ var SseTransport = class {
|
|
|
5327
5478
|
constructor(opts) {
|
|
5328
5479
|
this.url = opts.url;
|
|
5329
5480
|
this.headers = opts.headers ?? {};
|
|
5330
|
-
this.endpointReady = new Promise((
|
|
5331
|
-
this.resolveEndpoint =
|
|
5481
|
+
this.endpointReady = new Promise((resolve8, reject) => {
|
|
5482
|
+
this.resolveEndpoint = resolve8;
|
|
5332
5483
|
this.rejectEndpoint = reject;
|
|
5333
5484
|
});
|
|
5334
5485
|
this.endpointReady.catch(() => void 0);
|
|
@@ -5355,8 +5506,8 @@ var SseTransport = class {
|
|
|
5355
5506
|
continue;
|
|
5356
5507
|
}
|
|
5357
5508
|
if (this.closed) return;
|
|
5358
|
-
const next = await new Promise((
|
|
5359
|
-
this.waiters.push(
|
|
5509
|
+
const next = await new Promise((resolve8) => {
|
|
5510
|
+
this.waiters.push(resolve8);
|
|
5360
5511
|
});
|
|
5361
5512
|
if (next === null) return;
|
|
5362
5513
|
yield next;
|
|
@@ -5555,8 +5706,8 @@ async function trySection(load) {
|
|
|
5555
5706
|
}
|
|
5556
5707
|
|
|
5557
5708
|
// src/code/edit-blocks.ts
|
|
5558
|
-
import { existsSync as
|
|
5559
|
-
import { dirname as dirname4, resolve as
|
|
5709
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync10, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5710
|
+
import { dirname as dirname4, resolve as resolve7 } from "path";
|
|
5560
5711
|
var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
|
|
5561
5712
|
function parseEditBlocks(text) {
|
|
5562
5713
|
const out = [];
|
|
@@ -5574,8 +5725,8 @@ function parseEditBlocks(text) {
|
|
|
5574
5725
|
return out;
|
|
5575
5726
|
}
|
|
5576
5727
|
function applyEditBlock(block, rootDir) {
|
|
5577
|
-
const absRoot =
|
|
5578
|
-
const absTarget =
|
|
5728
|
+
const absRoot = resolve7(rootDir);
|
|
5729
|
+
const absTarget = resolve7(absRoot, block.path);
|
|
5579
5730
|
if (absTarget !== absRoot && !absTarget.startsWith(`${absRoot}${sep()}`)) {
|
|
5580
5731
|
return {
|
|
5581
5732
|
path: block.path,
|
|
@@ -5584,7 +5735,7 @@ function applyEditBlock(block, rootDir) {
|
|
|
5584
5735
|
};
|
|
5585
5736
|
}
|
|
5586
5737
|
const searchEmpty = block.search.length === 0;
|
|
5587
|
-
const exists =
|
|
5738
|
+
const exists = existsSync9(absTarget);
|
|
5588
5739
|
try {
|
|
5589
5740
|
if (!exists) {
|
|
5590
5741
|
if (!searchEmpty) {
|
|
@@ -5598,7 +5749,7 @@ function applyEditBlock(block, rootDir) {
|
|
|
5598
5749
|
writeFileSync3(absTarget, block.replace, "utf8");
|
|
5599
5750
|
return { path: block.path, status: "created" };
|
|
5600
5751
|
}
|
|
5601
|
-
const content =
|
|
5752
|
+
const content = readFileSync10(absTarget, "utf8");
|
|
5602
5753
|
if (searchEmpty) {
|
|
5603
5754
|
return {
|
|
5604
5755
|
path: block.path,
|
|
@@ -5625,19 +5776,19 @@ function applyEditBlocks(blocks, rootDir) {
|
|
|
5625
5776
|
return blocks.map((b) => applyEditBlock(b, rootDir));
|
|
5626
5777
|
}
|
|
5627
5778
|
function snapshotBeforeEdits(blocks, rootDir) {
|
|
5628
|
-
const absRoot =
|
|
5779
|
+
const absRoot = resolve7(rootDir);
|
|
5629
5780
|
const seen = /* @__PURE__ */ new Set();
|
|
5630
5781
|
const snapshots = [];
|
|
5631
5782
|
for (const b of blocks) {
|
|
5632
5783
|
if (seen.has(b.path)) continue;
|
|
5633
5784
|
seen.add(b.path);
|
|
5634
|
-
const abs =
|
|
5635
|
-
if (!
|
|
5785
|
+
const abs = resolve7(absRoot, b.path);
|
|
5786
|
+
if (!existsSync9(abs)) {
|
|
5636
5787
|
snapshots.push({ path: b.path, prevContent: null });
|
|
5637
5788
|
continue;
|
|
5638
5789
|
}
|
|
5639
5790
|
try {
|
|
5640
|
-
snapshots.push({ path: b.path, prevContent:
|
|
5791
|
+
snapshots.push({ path: b.path, prevContent: readFileSync10(abs, "utf8") });
|
|
5641
5792
|
} catch {
|
|
5642
5793
|
snapshots.push({ path: b.path, prevContent: null });
|
|
5643
5794
|
}
|
|
@@ -5645,9 +5796,9 @@ function snapshotBeforeEdits(blocks, rootDir) {
|
|
|
5645
5796
|
return snapshots;
|
|
5646
5797
|
}
|
|
5647
5798
|
function restoreSnapshots(snapshots, rootDir) {
|
|
5648
|
-
const absRoot =
|
|
5799
|
+
const absRoot = resolve7(rootDir);
|
|
5649
5800
|
return snapshots.map((snap) => {
|
|
5650
|
-
const abs =
|
|
5801
|
+
const abs = resolve7(absRoot, snap.path);
|
|
5651
5802
|
if (abs !== absRoot && !abs.startsWith(`${absRoot}${sep()}`)) {
|
|
5652
5803
|
return {
|
|
5653
5804
|
path: snap.path,
|
|
@@ -5657,7 +5808,7 @@ function restoreSnapshots(snapshots, rootDir) {
|
|
|
5657
5808
|
}
|
|
5658
5809
|
try {
|
|
5659
5810
|
if (snap.prevContent === null) {
|
|
5660
|
-
if (
|
|
5811
|
+
if (existsSync9(abs)) unlinkSync3(abs);
|
|
5661
5812
|
return {
|
|
5662
5813
|
path: snap.path,
|
|
5663
5814
|
status: "applied",
|
|
@@ -5680,7 +5831,7 @@ function sep() {
|
|
|
5680
5831
|
}
|
|
5681
5832
|
|
|
5682
5833
|
// src/code/prompt.ts
|
|
5683
|
-
import { existsSync as
|
|
5834
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
|
|
5684
5835
|
import { join as join8 } from "path";
|
|
5685
5836
|
var CODE_SYSTEM_PROMPT = `You are Reasonix Code, a coding assistant. You have filesystem tools (read_file, write_file, list_directory, search_files, etc.) rooted at the user's working directory.
|
|
5686
5837
|
|
|
@@ -5803,10 +5954,10 @@ Two different rules depending on which tool:
|
|
|
5803
5954
|
function codeSystemPrompt(rootDir) {
|
|
5804
5955
|
const withMemory = applyMemoryStack(CODE_SYSTEM_PROMPT, rootDir);
|
|
5805
5956
|
const gitignorePath = join8(rootDir, ".gitignore");
|
|
5806
|
-
if (!
|
|
5957
|
+
if (!existsSync10(gitignorePath)) return withMemory;
|
|
5807
5958
|
let content;
|
|
5808
5959
|
try {
|
|
5809
|
-
content =
|
|
5960
|
+
content = readFileSync11(gitignorePath, "utf8");
|
|
5810
5961
|
} catch {
|
|
5811
5962
|
return withMemory;
|
|
5812
5963
|
}
|
|
@@ -5826,7 +5977,7 @@ ${truncated}
|
|
|
5826
5977
|
}
|
|
5827
5978
|
|
|
5828
5979
|
// src/config.ts
|
|
5829
|
-
import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, readFileSync as
|
|
5980
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
|
|
5830
5981
|
import { homedir as homedir5 } from "os";
|
|
5831
5982
|
import { dirname as dirname5, join as join9 } from "path";
|
|
5832
5983
|
function defaultConfigPath() {
|
|
@@ -5834,7 +5985,7 @@ function defaultConfigPath() {
|
|
|
5834
5985
|
}
|
|
5835
5986
|
function readConfig(path = defaultConfigPath()) {
|
|
5836
5987
|
try {
|
|
5837
|
-
const raw =
|
|
5988
|
+
const raw = readFileSync12(path, "utf8");
|
|
5838
5989
|
const parsed = JSON.parse(raw);
|
|
5839
5990
|
if (parsed && typeof parsed === "object") return parsed;
|
|
5840
5991
|
} catch {
|
|
@@ -5869,7 +6020,7 @@ function redactKey(key) {
|
|
|
5869
6020
|
}
|
|
5870
6021
|
|
|
5871
6022
|
// src/version.ts
|
|
5872
|
-
import { existsSync as
|
|
6023
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "fs";
|
|
5873
6024
|
import { homedir as homedir6 } from "os";
|
|
5874
6025
|
import { dirname as dirname6, join as join10 } from "path";
|
|
5875
6026
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -5881,8 +6032,8 @@ function readPackageVersion() {
|
|
|
5881
6032
|
let dir = dirname6(fileURLToPath2(import.meta.url));
|
|
5882
6033
|
for (let i = 0; i < 6; i++) {
|
|
5883
6034
|
const p = join10(dir, "package.json");
|
|
5884
|
-
if (
|
|
5885
|
-
const pkg = JSON.parse(
|
|
6035
|
+
if (existsSync11(p)) {
|
|
6036
|
+
const pkg = JSON.parse(readFileSync13(p, "utf8"));
|
|
5886
6037
|
if (pkg?.name === "reasonix" && typeof pkg.version === "string") {
|
|
5887
6038
|
return pkg.version;
|
|
5888
6039
|
}
|
|
@@ -5901,7 +6052,7 @@ function cachePath(homeDirOverride) {
|
|
|
5901
6052
|
}
|
|
5902
6053
|
function readCache(homeDirOverride) {
|
|
5903
6054
|
try {
|
|
5904
|
-
const raw =
|
|
6055
|
+
const raw = readFileSync13(cachePath(homeDirOverride), "utf8");
|
|
5905
6056
|
const parsed = JSON.parse(raw);
|
|
5906
6057
|
if (parsed && typeof parsed.version === "string" && typeof parsed.checkedAt === "number") {
|
|
5907
6058
|
return parsed;
|
|
@@ -5970,7 +6121,7 @@ function isNpxInstall() {
|
|
|
5970
6121
|
}
|
|
5971
6122
|
|
|
5972
6123
|
// src/usage.ts
|
|
5973
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
6124
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync14, statSync as statSync5 } from "fs";
|
|
5974
6125
|
import { homedir as homedir7 } from "os";
|
|
5975
6126
|
import { dirname as dirname7, join as join11 } from "path";
|
|
5976
6127
|
function defaultUsageLogPath(homeDirOverride) {
|
|
@@ -5998,10 +6149,10 @@ function appendUsage(input) {
|
|
|
5998
6149
|
return record;
|
|
5999
6150
|
}
|
|
6000
6151
|
function readUsageLog(path = defaultUsageLogPath()) {
|
|
6001
|
-
if (!
|
|
6152
|
+
if (!existsSync12(path)) return [];
|
|
6002
6153
|
let raw;
|
|
6003
6154
|
try {
|
|
6004
|
-
raw =
|
|
6155
|
+
raw = readFileSync14(path, "utf8");
|
|
6005
6156
|
} catch {
|
|
6006
6157
|
return [];
|
|
6007
6158
|
}
|
|
@@ -6083,9 +6234,9 @@ function aggregateUsage(records, opts = {}) {
|
|
|
6083
6234
|
};
|
|
6084
6235
|
}
|
|
6085
6236
|
function formatLogSize(path = defaultUsageLogPath()) {
|
|
6086
|
-
if (!
|
|
6237
|
+
if (!existsSync12(path)) return "";
|
|
6087
6238
|
try {
|
|
6088
|
-
const s =
|
|
6239
|
+
const s = statSync5(path);
|
|
6089
6240
|
const bytes = s.size;
|
|
6090
6241
|
if (bytes < 1024) return `${bytes} B`;
|
|
6091
6242
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -6095,9 +6246,11 @@ function formatLogSize(path = defaultUsageLogPath()) {
|
|
|
6095
6246
|
}
|
|
6096
6247
|
}
|
|
6097
6248
|
export {
|
|
6249
|
+
AT_MENTION_PATTERN,
|
|
6098
6250
|
AppendOnlyLog,
|
|
6099
6251
|
CODE_SYSTEM_PROMPT,
|
|
6100
6252
|
CacheFirstLoop,
|
|
6253
|
+
DEFAULT_AT_MENTION_MAX_BYTES,
|
|
6101
6254
|
DEFAULT_MAX_RESULT_CHARS,
|
|
6102
6255
|
DEFAULT_MAX_RESULT_TOKENS,
|
|
6103
6256
|
DeepSeekClient,
|
|
@@ -6152,7 +6305,9 @@ export {
|
|
|
6152
6305
|
detectShellOperator,
|
|
6153
6306
|
diffTranscripts,
|
|
6154
6307
|
emptyPlanState,
|
|
6308
|
+
expandAtMentions,
|
|
6155
6309
|
fetchWithRetry,
|
|
6310
|
+
fixToolCallPairing,
|
|
6156
6311
|
flattenMcpResult,
|
|
6157
6312
|
flattenSchema,
|
|
6158
6313
|
forkRegistryExcluding,
|
|
@@ -6165,6 +6320,7 @@ export {
|
|
|
6165
6320
|
globalSettingsPath,
|
|
6166
6321
|
harvest,
|
|
6167
6322
|
healLoadedMessages,
|
|
6323
|
+
healLoadedMessagesByTokens,
|
|
6168
6324
|
htmlToText,
|
|
6169
6325
|
injectPowerShellUtf8,
|
|
6170
6326
|
inputCostUsd,
|