reasonix 0.50.0 → 0.51.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/dashboard/dist/app.css +1 -1
- package/dashboard/dist/app.js +24 -22
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{acp-6B25WIFF.js → acp-XEUHGG7X.js} +34 -31
- package/dist/cli/acp-XEUHGG7X.js.map +1 -0
- package/dist/cli/chat-NJ2Q5KHG.js +50 -0
- package/dist/cli/{chunk-OPGWCKKU.js → chunk-2HVTBFCI.js} +3 -3
- package/dist/cli/{chunk-AJIZ5KFK.js → chunk-2WUEAI2I.js} +3 -3
- package/dist/cli/{chunk-I4Q3QT4W.js → chunk-36BM7INR.js} +2 -2
- package/dist/cli/{chunk-3RNFYDDM.js → chunk-3BTK5BHI.js} +11 -7
- package/dist/cli/chunk-3BTK5BHI.js.map +1 -0
- package/dist/cli/{chunk-GMSAB2TC.js → chunk-3YRTIWFX.js} +2 -2
- package/dist/cli/{chunk-NLRC3DWQ.js → chunk-544J4PXD.js} +5 -5
- package/dist/cli/{chunk-7WITYWKN.js → chunk-5AIDYVH2.js} +2 -2
- package/dist/cli/{chunk-ALCOQP6R.js → chunk-5BBC6YMV.js} +5 -5
- package/dist/cli/{chunk-S4XVGLRW.js → chunk-6UNHNVJR.js} +72 -5
- package/dist/cli/chunk-6UNHNVJR.js.map +1 -0
- package/dist/cli/{chunk-IK6WWRIX.js → chunk-6XWXIVQ3.js} +38 -22
- package/dist/cli/chunk-6XWXIVQ3.js.map +1 -0
- package/dist/cli/{chunk-AAHB2PFX.js → chunk-7YB26OQO.js} +4 -4
- package/dist/cli/chunk-7YB26OQO.js.map +1 -0
- package/dist/cli/{chunk-MXWPAPZW.js → chunk-A5PBEIJ7.js} +53 -10
- package/dist/cli/chunk-A5PBEIJ7.js.map +1 -0
- package/dist/cli/{chunk-FQSQFCBI.js → chunk-BA5R6BAE.js} +2 -2
- package/dist/cli/{chunk-XWPZHWC2.js → chunk-BM6BBFAV.js} +2 -2
- package/dist/cli/{chunk-CAGKEGNE.js → chunk-BOWSNGQC.js} +52 -140
- package/dist/cli/chunk-BOWSNGQC.js.map +1 -0
- package/dist/cli/{chunk-EZ57UEZQ.js → chunk-C2MRSJTV.js} +2 -2
- package/dist/cli/{chunk-PYIZZAVQ.js → chunk-DVD67FXQ.js} +1716 -4
- package/dist/cli/chunk-DVD67FXQ.js.map +1 -0
- package/dist/cli/{chunk-ZAXMJANP.js → chunk-EAMXOWUW.js} +3 -3
- package/dist/cli/{chunk-TX652NBA.js → chunk-EWVFGYT6.js} +2 -2
- package/dist/cli/{chunk-IBRTU5WO.js → chunk-FP7IOWBQ.js} +18 -1182
- package/dist/cli/chunk-FP7IOWBQ.js.map +1 -0
- package/dist/cli/{chunk-I6FBSTTR.js → chunk-HGK57NBN.js} +9 -353
- package/dist/cli/chunk-HGK57NBN.js.map +1 -0
- package/dist/cli/chunk-JHWQDJZA.js +80 -0
- package/dist/cli/chunk-JHWQDJZA.js.map +1 -0
- package/dist/cli/{chunk-X2BQZQEE.js → chunk-K3QJ3GKI.js} +3 -3
- package/dist/cli/{chunk-GPUH2BNM.js → chunk-K4YQFULP.js} +612 -254
- package/dist/cli/chunk-K4YQFULP.js.map +1 -0
- package/dist/cli/chunk-L3VPEESB.js +31 -0
- package/dist/cli/chunk-L3VPEESB.js.map +1 -0
- package/dist/cli/{chunk-ENFBF6HI.js → chunk-N4SEBLU4.js} +383 -5
- package/dist/cli/chunk-N4SEBLU4.js.map +1 -0
- package/dist/cli/chunk-NRROJXXT.js +879 -0
- package/dist/cli/chunk-NRROJXXT.js.map +1 -0
- package/dist/cli/{chunk-3KRRTLC5.js → chunk-R6KIHEF3.js} +1619 -1036
- package/dist/cli/chunk-R6KIHEF3.js.map +1 -0
- package/dist/cli/{chunk-VVMY4M7J.js → chunk-SBHF5NWD.js} +27 -4
- package/dist/cli/chunk-SBHF5NWD.js.map +1 -0
- package/dist/cli/{chunk-OWA42BKS.js → chunk-SXSAWOB7.js} +14 -14
- package/dist/cli/{chunk-6IUMTRFP.js → chunk-UMZ6KHTS.js} +2 -2
- package/dist/cli/{chunk-7X4JJOO7.js → chunk-UO6E7FN3.js} +69 -5
- package/dist/cli/{chunk-7X4JJOO7.js.map → chunk-UO6E7FN3.js.map} +1 -1
- package/dist/cli/{chunk-3ZZXQ3CZ.js → chunk-UPW544V3.js} +2 -2
- package/dist/cli/{chunk-XJZWMU5P.js → chunk-WPOKBW5E.js} +2 -2
- package/dist/cli/{chunk-WSBFVOCO.js → chunk-Z3MKG7MQ.js} +2 -2
- package/dist/cli/{code-TBK2TASK.js → code-BMXLBC7D.js} +37 -36
- package/dist/cli/{code-TBK2TASK.js.map → code-BMXLBC7D.js.map} +1 -1
- package/dist/cli/{commands-NXTKSQTN.js → commands-E4RZXMF6.js} +5 -5
- package/dist/cli/{commit-IR5SPP7A.js → commit-KSRQ64IL.js} +3 -3
- package/dist/cli/{config-XK5WQGTS.js → config-QNDONOTU.js} +4 -2
- package/dist/cli/{desktop-5NTQBADL.js → desktop-H3ZHIMDA.js} +83 -37
- package/dist/cli/desktop-H3ZHIMDA.js.map +1 -0
- package/dist/cli/{diff-JNYX5BSZ.js → diff-I4PYI43W.js} +9 -9
- package/dist/cli/{doctor-IKYLUFXX.js → doctor-Y2E4MY2F.js} +12 -12
- package/dist/cli/{events-HSC57ONU.js → events-47HOT7ZA.js} +5 -5
- package/dist/cli/find-in-code-YLEIK5FK.js +145 -0
- package/dist/cli/find-in-code-YLEIK5FK.js.map +1 -0
- package/dist/cli/index.js +95 -44
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-BDJJWOCD.js → mcp-76DK63ZB.js} +3 -3
- package/dist/cli/{mcp-browse-NJRZDI6V.js → mcp-browse-SDNUGO74.js} +3 -3
- package/dist/cli/{mcp-inspect-Y62NWZQL.js → mcp-inspect-BL5DEO5M.js} +3 -3
- package/dist/cli/{prompt-UTOIFUQC.js → prompt-JLATI3P7.js} +5 -5
- package/dist/cli/{prune-sessions-UCUD4XAP.js → prune-sessions-WHZDFUKD.js} +4 -4
- package/dist/cli/{replay-VVIN64MN.js → replay-MHXS7C7Z.js} +10 -10
- package/dist/cli/{run-76OBDZFB.js → run-SXNCPRJE.js} +22 -22
- package/dist/cli/{server-SZZDKTH2.js → server-GEHOE6CO.js} +61 -35
- package/dist/cli/server-GEHOE6CO.js.map +1 -0
- package/dist/cli/{sessions-FZTGRCM5.js → sessions-EPBFYISL.js} +18 -18
- package/dist/cli/{setup-4UNENGOE.js → setup-IW2XR5XI.js} +8 -7
- package/dist/cli/setup-IW2XR5XI.js.map +1 -0
- package/dist/cli/{stats-F4NDOD7D.js → stats-4WB4XHBP.js} +6 -6
- package/dist/cli/symbols-UQ274IOB.js +167 -0
- package/dist/cli/symbols-UQ274IOB.js.map +1 -0
- package/dist/cli/version-4SP3DLLH.js +33 -0
- package/dist/index.d.ts +25 -6
- package/dist/index.js +2700 -578
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/scripts/postinstall.mjs +10 -0
- package/dist/cli/acp-6B25WIFF.js.map +0 -1
- package/dist/cli/chat-7WASPB4O.js +0 -50
- package/dist/cli/chunk-3KRRTLC5.js.map +0 -1
- package/dist/cli/chunk-3RNFYDDM.js.map +0 -1
- package/dist/cli/chunk-AAHB2PFX.js.map +0 -1
- package/dist/cli/chunk-CAGKEGNE.js.map +0 -1
- package/dist/cli/chunk-ENFBF6HI.js.map +0 -1
- package/dist/cli/chunk-GPUH2BNM.js.map +0 -1
- package/dist/cli/chunk-I6FBSTTR.js.map +0 -1
- package/dist/cli/chunk-IBRTU5WO.js.map +0 -1
- package/dist/cli/chunk-IK6WWRIX.js.map +0 -1
- package/dist/cli/chunk-MXWPAPZW.js.map +0 -1
- package/dist/cli/chunk-PYIZZAVQ.js.map +0 -1
- package/dist/cli/chunk-S4XVGLRW.js.map +0 -1
- package/dist/cli/chunk-VVMY4M7J.js.map +0 -1
- package/dist/cli/desktop-5NTQBADL.js.map +0 -1
- package/dist/cli/server-SZZDKTH2.js.map +0 -1
- package/dist/cli/setup-4UNENGOE.js.map +0 -1
- package/dist/cli/version-LUVTWHLL.js +0 -33
- /package/dist/cli/{chat-7WASPB4O.js.map → chat-NJ2Q5KHG.js.map} +0 -0
- /package/dist/cli/{chunk-OPGWCKKU.js.map → chunk-2HVTBFCI.js.map} +0 -0
- /package/dist/cli/{chunk-AJIZ5KFK.js.map → chunk-2WUEAI2I.js.map} +0 -0
- /package/dist/cli/{chunk-I4Q3QT4W.js.map → chunk-36BM7INR.js.map} +0 -0
- /package/dist/cli/{chunk-GMSAB2TC.js.map → chunk-3YRTIWFX.js.map} +0 -0
- /package/dist/cli/{chunk-NLRC3DWQ.js.map → chunk-544J4PXD.js.map} +0 -0
- /package/dist/cli/{chunk-7WITYWKN.js.map → chunk-5AIDYVH2.js.map} +0 -0
- /package/dist/cli/{chunk-ALCOQP6R.js.map → chunk-5BBC6YMV.js.map} +0 -0
- /package/dist/cli/{chunk-FQSQFCBI.js.map → chunk-BA5R6BAE.js.map} +0 -0
- /package/dist/cli/{chunk-XWPZHWC2.js.map → chunk-BM6BBFAV.js.map} +0 -0
- /package/dist/cli/{chunk-EZ57UEZQ.js.map → chunk-C2MRSJTV.js.map} +0 -0
- /package/dist/cli/{chunk-ZAXMJANP.js.map → chunk-EAMXOWUW.js.map} +0 -0
- /package/dist/cli/{chunk-TX652NBA.js.map → chunk-EWVFGYT6.js.map} +0 -0
- /package/dist/cli/{chunk-X2BQZQEE.js.map → chunk-K3QJ3GKI.js.map} +0 -0
- /package/dist/cli/{chunk-OWA42BKS.js.map → chunk-SXSAWOB7.js.map} +0 -0
- /package/dist/cli/{chunk-6IUMTRFP.js.map → chunk-UMZ6KHTS.js.map} +0 -0
- /package/dist/cli/{chunk-3ZZXQ3CZ.js.map → chunk-UPW544V3.js.map} +0 -0
- /package/dist/cli/{chunk-XJZWMU5P.js.map → chunk-WPOKBW5E.js.map} +0 -0
- /package/dist/cli/{chunk-WSBFVOCO.js.map → chunk-Z3MKG7MQ.js.map} +0 -0
- /package/dist/cli/{commands-NXTKSQTN.js.map → commands-E4RZXMF6.js.map} +0 -0
- /package/dist/cli/{commit-IR5SPP7A.js.map → commit-KSRQ64IL.js.map} +0 -0
- /package/dist/cli/{config-XK5WQGTS.js.map → config-QNDONOTU.js.map} +0 -0
- /package/dist/cli/{diff-JNYX5BSZ.js.map → diff-I4PYI43W.js.map} +0 -0
- /package/dist/cli/{doctor-IKYLUFXX.js.map → doctor-Y2E4MY2F.js.map} +0 -0
- /package/dist/cli/{events-HSC57ONU.js.map → events-47HOT7ZA.js.map} +0 -0
- /package/dist/cli/{mcp-BDJJWOCD.js.map → mcp-76DK63ZB.js.map} +0 -0
- /package/dist/cli/{mcp-browse-NJRZDI6V.js.map → mcp-browse-SDNUGO74.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-Y62NWZQL.js.map → mcp-inspect-BL5DEO5M.js.map} +0 -0
- /package/dist/cli/{prompt-UTOIFUQC.js.map → prompt-JLATI3P7.js.map} +0 -0
- /package/dist/cli/{prune-sessions-UCUD4XAP.js.map → prune-sessions-WHZDFUKD.js.map} +0 -0
- /package/dist/cli/{replay-VVIN64MN.js.map → replay-MHXS7C7Z.js.map} +0 -0
- /package/dist/cli/{run-76OBDZFB.js.map → run-SXNCPRJE.js.map} +0 -0
- /package/dist/cli/{sessions-FZTGRCM5.js.map → sessions-EPBFYISL.js.map} +0 -0
- /package/dist/cli/{stats-F4NDOD7D.js.map → stats-4WB4XHBP.js.map} +0 -0
- /package/dist/cli/{version-LUVTWHLL.js.map → version-4SP3DLLH.js.map} +0 -0
|
@@ -7,32 +7,39 @@ import {
|
|
|
7
7
|
decodeFileBuffer,
|
|
8
8
|
encodeFile,
|
|
9
9
|
pauseGate
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-UMZ6KHTS.js";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
DEEPSEEK_CONTEXT_TOKENS,
|
|
13
|
+
DEFAULT_CONTEXT_TOKENS,
|
|
14
|
+
SessionStats
|
|
15
|
+
} from "./chunk-BA5R6BAE.js";
|
|
15
16
|
import {
|
|
17
|
+
MemoryStore,
|
|
16
18
|
NEGATIVE_CLAIM_RULE,
|
|
17
19
|
PROJECT_MEMORY_FILES,
|
|
18
20
|
PROJECT_MEMORY_MAX_CHARS,
|
|
19
21
|
TUI_FORMATTING_RULES,
|
|
20
|
-
memoryEnabled
|
|
21
|
-
|
|
22
|
+
memoryEnabled,
|
|
23
|
+
sanitizeMemoryName
|
|
24
|
+
} from "./chunk-N4SEBLU4.js";
|
|
22
25
|
import {
|
|
23
26
|
countTokens,
|
|
24
27
|
countTokensBounded,
|
|
25
28
|
estimateRequestTokens
|
|
26
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-BOWSNGQC.js";
|
|
30
|
+
import {
|
|
31
|
+
Usage
|
|
32
|
+
} from "./chunk-C2MRSJTV.js";
|
|
27
33
|
import {
|
|
28
34
|
formatHookOutcomeMessage,
|
|
29
35
|
runHooks
|
|
30
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-2WUEAI2I.js";
|
|
31
37
|
import {
|
|
38
|
+
TtlLruCache,
|
|
32
39
|
ignoredByLayers,
|
|
33
40
|
loadGitignoreAt,
|
|
34
41
|
loadGitignoreAtSync
|
|
35
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-6UNHNVJR.js";
|
|
36
43
|
import {
|
|
37
44
|
appendSessionMessage,
|
|
38
45
|
archiveSession,
|
|
@@ -41,18 +48,10 @@ import {
|
|
|
41
48
|
patchSessionMeta,
|
|
42
49
|
rewriteSession,
|
|
43
50
|
timestampSuffix
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import {
|
|
46
|
-
Usage
|
|
47
|
-
} from "./chunk-EZ57UEZQ.js";
|
|
48
|
-
import {
|
|
49
|
-
DEEPSEEK_CONTEXT_TOKENS,
|
|
50
|
-
DEFAULT_CONTEXT_TOKENS,
|
|
51
|
-
SessionStats
|
|
52
|
-
} from "./chunk-FQSQFCBI.js";
|
|
51
|
+
} from "./chunk-6XWXIVQ3.js";
|
|
53
52
|
import {
|
|
54
53
|
t
|
|
55
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-DVD67FXQ.js";
|
|
56
55
|
import {
|
|
57
56
|
DEFAULT_INDEX_EXCLUDES,
|
|
58
57
|
ToolRateLimiter,
|
|
@@ -67,7 +66,7 @@ import {
|
|
|
67
66
|
require_picomatch,
|
|
68
67
|
webSearchEndpoint,
|
|
69
68
|
webSearchEngine
|
|
70
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-A5PBEIJ7.js";
|
|
71
70
|
import {
|
|
72
71
|
__commonJS,
|
|
73
72
|
__esm,
|
|
@@ -2604,10 +2603,10 @@ var require_helpers = __commonJS({
|
|
|
2604
2603
|
return !arr.includes(node, i + 1);
|
|
2605
2604
|
});
|
|
2606
2605
|
nodes.sort(function(a, b) {
|
|
2607
|
-
var
|
|
2608
|
-
if (
|
|
2606
|
+
var relative8 = compareDocumentPosition(a, b);
|
|
2607
|
+
if (relative8 & DocumentPosition.PRECEDING) {
|
|
2609
2608
|
return -1;
|
|
2610
|
-
} else if (
|
|
2609
|
+
} else if (relative8 & DocumentPosition.FOLLOWING) {
|
|
2611
2610
|
return 1;
|
|
2612
2611
|
}
|
|
2613
2612
|
return 0;
|
|
@@ -6057,12 +6056,12 @@ async function waitForReady(ready, timeoutMs, serverName, signal) {
|
|
|
6057
6056
|
let timer;
|
|
6058
6057
|
let onAbort;
|
|
6059
6058
|
try {
|
|
6060
|
-
await new Promise((
|
|
6059
|
+
await new Promise((resolve7, reject) => {
|
|
6061
6060
|
ready.then(
|
|
6062
6061
|
() => {
|
|
6063
6062
|
if (settled) return;
|
|
6064
6063
|
settled = true;
|
|
6065
|
-
|
|
6064
|
+
resolve7();
|
|
6066
6065
|
},
|
|
6067
6066
|
(err) => {
|
|
6068
6067
|
if (settled) return;
|
|
@@ -6168,25 +6167,30 @@ function validateResultShape(result) {
|
|
|
6168
6167
|
}
|
|
6169
6168
|
}
|
|
6170
6169
|
}
|
|
6171
|
-
function truncateForModel(s, maxChars) {
|
|
6170
|
+
function truncateForModel(s, maxChars, extraNote) {
|
|
6172
6171
|
if (s.length <= maxChars) return s;
|
|
6173
6172
|
const tailBudget = Math.min(1024, Math.floor(maxChars * 0.1));
|
|
6174
6173
|
const headBudget = Math.max(0, maxChars - tailBudget);
|
|
6175
6174
|
const head = s.slice(0, headBudget);
|
|
6176
6175
|
const tail = s.slice(-tailBudget);
|
|
6177
6176
|
const dropped = s.length - head.length - tail.length;
|
|
6177
|
+
const note = extraNote ? ` \u2014 ${extraNote}` : "";
|
|
6178
6178
|
return `${head}
|
|
6179
6179
|
|
|
6180
|
-
[\u2026truncated ${dropped} chars \u2014 raise BridgeOptions.maxResultChars, or call the tool with a narrower scope (filter, head, pagination)\u2026]
|
|
6180
|
+
[\u2026truncated ${dropped} chars \u2014 raise BridgeOptions.maxResultChars, or call the tool with a narrower scope (filter, head, pagination)${note}\u2026]
|
|
6181
6181
|
|
|
6182
6182
|
${tail}`;
|
|
6183
6183
|
}
|
|
6184
|
-
function truncateForModelByTokens(s, maxTokens) {
|
|
6184
|
+
function truncateForModelByTokens(s, maxTokens, extraNote) {
|
|
6185
6185
|
if (maxTokens <= 0) return "";
|
|
6186
6186
|
if (s.length <= maxTokens) return s;
|
|
6187
6187
|
if (s.length <= maxTokens * 4) {
|
|
6188
|
-
const
|
|
6189
|
-
if (
|
|
6188
|
+
const est = countTokensBounded(s);
|
|
6189
|
+
if (Math.ceil(est * 1.15) <= maxTokens) return s;
|
|
6190
|
+
if (est <= maxTokens) {
|
|
6191
|
+
const tokens = countTokens(s);
|
|
6192
|
+
if (tokens <= maxTokens) return s;
|
|
6193
|
+
}
|
|
6190
6194
|
}
|
|
6191
6195
|
const markerOverhead = 48;
|
|
6192
6196
|
const contentBudget = Math.max(0, maxTokens - markerOverhead);
|
|
@@ -6202,9 +6206,10 @@ function truncateForModelByTokens(s, maxTokens) {
|
|
|
6202
6206
|
const ratio = sampleChars > 0 ? sampleTokens / sampleChars : 0.3;
|
|
6203
6207
|
const estTotalTokens = Math.ceil(s.length * ratio);
|
|
6204
6208
|
const droppedTokens = Math.max(0, estTotalTokens - sampleTokens);
|
|
6209
|
+
const note = extraNote ? ` \u2014 ${extraNote}` : "";
|
|
6205
6210
|
return `${head}
|
|
6206
6211
|
|
|
6207
|
-
[\u2026truncated ~${droppedTokens} tokens (${droppedChars} chars) \u2014 raise BridgeOptions.maxResultTokens, or call the tool with a narrower scope (filter, head, pagination)\u2026]
|
|
6212
|
+
[\u2026truncated ~${droppedTokens} tokens (${droppedChars} chars) \u2014 raise BridgeOptions.maxResultTokens, or call the tool with a narrower scope (filter, head, pagination)${note}\u2026]
|
|
6208
6213
|
|
|
6209
6214
|
${tail}`;
|
|
6210
6215
|
}
|
|
@@ -6310,6 +6315,81 @@ function setByPath(target, path, value) {
|
|
|
6310
6315
|
cur[path[path.length - 1]] = value;
|
|
6311
6316
|
}
|
|
6312
6317
|
|
|
6318
|
+
// src/tools/truncated-result-saver.ts
|
|
6319
|
+
import { randomUUID } from "crypto";
|
|
6320
|
+
import {
|
|
6321
|
+
chmodSync,
|
|
6322
|
+
existsSync,
|
|
6323
|
+
mkdirSync,
|
|
6324
|
+
readdirSync,
|
|
6325
|
+
rmSync,
|
|
6326
|
+
statSync,
|
|
6327
|
+
writeFileSync
|
|
6328
|
+
} from "fs";
|
|
6329
|
+
import { homedir } from "os";
|
|
6330
|
+
import { join, relative, resolve } from "path";
|
|
6331
|
+
var TRUNCATED_DIR = "truncated-results";
|
|
6332
|
+
var DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
6333
|
+
function sanitizeToolName(name) {
|
|
6334
|
+
return name.replace(/[^\w\-]/g, "_").slice(0, 48) || "unknown";
|
|
6335
|
+
}
|
|
6336
|
+
function storageDir(rootDir) {
|
|
6337
|
+
const base = rootDir ? join(resolve(rootDir), ".reasonix") : join(homedir(), ".reasonix");
|
|
6338
|
+
return join(base, TRUNCATED_DIR);
|
|
6339
|
+
}
|
|
6340
|
+
function resultFilename(toolName) {
|
|
6341
|
+
const ts = Date.now().toString();
|
|
6342
|
+
const suffix = randomUUID().slice(0, 8);
|
|
6343
|
+
const safeName = sanitizeToolName(toolName);
|
|
6344
|
+
return `${ts}-${suffix}-${safeName}.txt`;
|
|
6345
|
+
}
|
|
6346
|
+
function saveTruncatedResult(content, toolName, rootDir) {
|
|
6347
|
+
cleanupOldResults(rootDir);
|
|
6348
|
+
const dir = storageDir(rootDir);
|
|
6349
|
+
if (!existsSync(dir)) {
|
|
6350
|
+
mkdirSync(dir, { recursive: true });
|
|
6351
|
+
}
|
|
6352
|
+
const filename = resultFilename(toolName);
|
|
6353
|
+
const absPath = join(dir, filename);
|
|
6354
|
+
writeFileSync(absPath, content, "utf-8");
|
|
6355
|
+
try {
|
|
6356
|
+
chmodSync(absPath, 384);
|
|
6357
|
+
} catch {
|
|
6358
|
+
}
|
|
6359
|
+
if (rootDir) {
|
|
6360
|
+
const absRoot = resolve(rootDir);
|
|
6361
|
+
return relative(absRoot, absPath).replaceAll("\\", "/");
|
|
6362
|
+
}
|
|
6363
|
+
return absPath.replaceAll("\\", "/");
|
|
6364
|
+
}
|
|
6365
|
+
function cleanupOldResults(rootDir, maxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
6366
|
+
const dir = storageDir(rootDir);
|
|
6367
|
+
if (!existsSync(dir)) return;
|
|
6368
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
6369
|
+
let entries;
|
|
6370
|
+
try {
|
|
6371
|
+
entries = readdirSync(dir);
|
|
6372
|
+
} catch {
|
|
6373
|
+
return;
|
|
6374
|
+
}
|
|
6375
|
+
for (const entry of entries) {
|
|
6376
|
+
if (!entry.endsWith(".txt")) continue;
|
|
6377
|
+
const abs = join(dir, entry);
|
|
6378
|
+
try {
|
|
6379
|
+
const st = statSync(abs);
|
|
6380
|
+
if (st.isFile() && st.mtimeMs < cutoff) {
|
|
6381
|
+
rmSync(abs);
|
|
6382
|
+
}
|
|
6383
|
+
} catch {
|
|
6384
|
+
}
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
function shouldSkipSave(toolName, skipTruncationSave) {
|
|
6388
|
+
if (skipTruncationSave) return true;
|
|
6389
|
+
const alwaysSkip = /* @__PURE__ */ new Set(["get_env", "everything_get-env"]);
|
|
6390
|
+
return alwaysSkip.has(toolName);
|
|
6391
|
+
}
|
|
6392
|
+
|
|
6313
6393
|
// src/tools.ts
|
|
6314
6394
|
var ToolRegistry = class {
|
|
6315
6395
|
_tools = /* @__PURE__ */ new Map();
|
|
@@ -6487,7 +6567,20 @@ var ToolRegistry = class {
|
|
|
6487
6567
|
if (opts.maxResultChars !== void 0) {
|
|
6488
6568
|
clipped = truncateForModel(clipped, opts.maxResultChars);
|
|
6489
6569
|
}
|
|
6490
|
-
|
|
6570
|
+
if (clipped !== str && !shouldSkipSave(name, tool?.skipTruncationSave)) {
|
|
6571
|
+
const relPath = saveTruncatedResult(str, name, opts.rootDir ?? process.cwd());
|
|
6572
|
+
const note = `Full result saved at: ${relPath}`;
|
|
6573
|
+
let annotated = str;
|
|
6574
|
+
if (opts.maxResultTokens !== void 0) {
|
|
6575
|
+
annotated = truncateForModelByTokens(annotated, opts.maxResultTokens, note);
|
|
6576
|
+
}
|
|
6577
|
+
if (opts.maxResultChars !== void 0) {
|
|
6578
|
+
annotated = truncateForModel(annotated, opts.maxResultChars, note);
|
|
6579
|
+
}
|
|
6580
|
+
finalResult = annotated;
|
|
6581
|
+
} else {
|
|
6582
|
+
finalResult = clipped;
|
|
6583
|
+
}
|
|
6491
6584
|
} catch (err) {
|
|
6492
6585
|
const e = err;
|
|
6493
6586
|
if (typeof e.toToolResult === "function") {
|
|
@@ -7054,8 +7147,88 @@ var InflightSet = class {
|
|
|
7054
7147
|
}
|
|
7055
7148
|
};
|
|
7056
7149
|
|
|
7150
|
+
// src/loop/dispatch.ts
|
|
7151
|
+
function readParallelMax() {
|
|
7152
|
+
const raw = Number.parseInt(process.env.REASONIX_PARALLEL_MAX ?? "", 10);
|
|
7153
|
+
return Number.isFinite(raw) && raw >= 1 ? Math.min(raw, 16) : 3;
|
|
7154
|
+
}
|
|
7155
|
+
function readDispatchSerial() {
|
|
7156
|
+
return (process.env.REASONIX_TOOL_DISPATCH ?? "auto").toLowerCase() === "serial";
|
|
7157
|
+
}
|
|
7158
|
+
async function* dispatchToolCallsChunked(repairedCalls, ctx) {
|
|
7159
|
+
const dispatchSerial = readDispatchSerial();
|
|
7160
|
+
const parallelMax = readParallelMax();
|
|
7161
|
+
let callIdx = 0;
|
|
7162
|
+
while (callIdx < repairedCalls.length) {
|
|
7163
|
+
const chunk = [];
|
|
7164
|
+
if (!dispatchSerial) {
|
|
7165
|
+
while (callIdx < repairedCalls.length && chunk.length < parallelMax && ctx.isParallelSafe(repairedCalls[callIdx]?.function?.name ?? "")) {
|
|
7166
|
+
chunk.push(repairedCalls[callIdx++]);
|
|
7167
|
+
}
|
|
7168
|
+
}
|
|
7169
|
+
if (chunk.length === 0) {
|
|
7170
|
+
chunk.push(repairedCalls[callIdx++]);
|
|
7171
|
+
}
|
|
7172
|
+
for (const call of chunk) {
|
|
7173
|
+
const callId = ctx.inflightIdFor(call);
|
|
7174
|
+
ctx.inflightAdd(callId);
|
|
7175
|
+
yield {
|
|
7176
|
+
turn: ctx.turn,
|
|
7177
|
+
role: "tool_start",
|
|
7178
|
+
content: "",
|
|
7179
|
+
toolName: call.function?.name ?? "",
|
|
7180
|
+
toolArgs: call.function?.arguments ?? "{}",
|
|
7181
|
+
callId
|
|
7182
|
+
};
|
|
7183
|
+
}
|
|
7184
|
+
const settled = await Promise.allSettled(chunk.map((c) => ctx.runOne(c, ctx.signal)));
|
|
7185
|
+
for (let k = 0; k < chunk.length; k++) {
|
|
7186
|
+
const call = chunk[k];
|
|
7187
|
+
const name = call.function?.name ?? "";
|
|
7188
|
+
const args = call.function?.arguments ?? "{}";
|
|
7189
|
+
const s = settled[k];
|
|
7190
|
+
let result;
|
|
7191
|
+
let preWarnings = [];
|
|
7192
|
+
let postWarnings = [];
|
|
7193
|
+
if (s.status === "fulfilled") {
|
|
7194
|
+
preWarnings = s.value.preWarnings;
|
|
7195
|
+
postWarnings = s.value.postWarnings;
|
|
7196
|
+
result = s.value.result;
|
|
7197
|
+
} else {
|
|
7198
|
+
const err = s.reason instanceof Error ? s.reason : new Error(String(s.reason));
|
|
7199
|
+
result = JSON.stringify({ error: `${err.name}: ${err.message}` });
|
|
7200
|
+
}
|
|
7201
|
+
for (const w of preWarnings) yield w;
|
|
7202
|
+
for (const w of postWarnings) yield w;
|
|
7203
|
+
const rateLimited = parseRateLimitedToolResult(result);
|
|
7204
|
+
if (rateLimited && !ctx.rateLimitState.shown) {
|
|
7205
|
+
ctx.rateLimitState.shown = true;
|
|
7206
|
+
yield {
|
|
7207
|
+
turn: ctx.turn,
|
|
7208
|
+
role: "warning",
|
|
7209
|
+
content: rateLimited.message
|
|
7210
|
+
};
|
|
7211
|
+
}
|
|
7212
|
+
ctx.appendAndPersist({
|
|
7213
|
+
role: "tool",
|
|
7214
|
+
tool_call_id: call.id ?? "",
|
|
7215
|
+
name,
|
|
7216
|
+
content: result
|
|
7217
|
+
});
|
|
7218
|
+
yield {
|
|
7219
|
+
turn: ctx.turn,
|
|
7220
|
+
role: "tool",
|
|
7221
|
+
content: result,
|
|
7222
|
+
toolName: name,
|
|
7223
|
+
toolArgs: args,
|
|
7224
|
+
callId: ctx.inflightIdFor(call)
|
|
7225
|
+
};
|
|
7226
|
+
}
|
|
7227
|
+
}
|
|
7228
|
+
}
|
|
7229
|
+
|
|
7057
7230
|
// src/loop/errors.ts
|
|
7058
|
-
function formatLoopError(err, probe) {
|
|
7231
|
+
function formatLoopError(err, probe, opts) {
|
|
7059
7232
|
const msg = err.message ?? "";
|
|
7060
7233
|
if (msg.includes("maximum context length")) {
|
|
7061
7234
|
const reqMatch = msg.match(/requested\s+(\d+)\s+tokens/);
|
|
@@ -7072,7 +7245,7 @@ function formatLoopError(err, probe) {
|
|
|
7072
7245
|
if (status === "422") return t("errors.badparam422", { inner });
|
|
7073
7246
|
if (status === "400") return t("errors.badrequest400", { inner });
|
|
7074
7247
|
if (status === "429") return t("errors.concurrency429", { inner });
|
|
7075
|
-
if (is5xxStatus(status)) return
|
|
7248
|
+
if (is5xxStatus(status)) return format5xx(status, probe, opts?.upstreamHost);
|
|
7076
7249
|
return msg;
|
|
7077
7250
|
}
|
|
7078
7251
|
function is5xxError(err) {
|
|
@@ -7084,15 +7257,40 @@ async function probeDeepSeekReachable(client, timeoutMs = 1500) {
|
|
|
7084
7257
|
const balance = await client.getBalance({ signal: AbortSignal.timeout(timeoutMs) });
|
|
7085
7258
|
return { reachable: balance !== null };
|
|
7086
7259
|
}
|
|
7260
|
+
function isDeepSeekHost(baseUrl) {
|
|
7261
|
+
if (!baseUrl) return false;
|
|
7262
|
+
try {
|
|
7263
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
7264
|
+
return host === "api.deepseek.com";
|
|
7265
|
+
} catch {
|
|
7266
|
+
return false;
|
|
7267
|
+
}
|
|
7268
|
+
}
|
|
7087
7269
|
function is5xxStatus(status) {
|
|
7088
7270
|
return status === "500" || status === "502" || status === "503" || status === "504";
|
|
7089
7271
|
}
|
|
7272
|
+
function format5xx(status, probe, upstreamHost) {
|
|
7273
|
+
if (upstreamHost !== void 0 && !isDeepSeekHost(upstreamHost)) {
|
|
7274
|
+
return formatUpstream5xx(status, upstreamHost);
|
|
7275
|
+
}
|
|
7276
|
+
return formatDeepSeek5xx(status, probe);
|
|
7277
|
+
}
|
|
7090
7278
|
function formatDeepSeek5xx(status, probe) {
|
|
7091
7279
|
const head = t("errors.deepseek5xxHead", { status });
|
|
7092
7280
|
const probeNote = probe === void 0 ? "" : probe.reachable ? t("errors.deepseek5xxReachable") : t("errors.deepseek5xxUnreachable");
|
|
7093
7281
|
const action = probe?.reachable === false ? t("errors.deepseek5xxActionNetwork") : t("errors.deepseek5xxActionRetry");
|
|
7094
7282
|
return `${head}${probeNote}${action}`;
|
|
7095
7283
|
}
|
|
7284
|
+
function formatUpstream5xx(status, baseUrl) {
|
|
7285
|
+
let host = baseUrl;
|
|
7286
|
+
try {
|
|
7287
|
+
host = new URL(baseUrl).host || baseUrl;
|
|
7288
|
+
} catch {
|
|
7289
|
+
}
|
|
7290
|
+
const head = t("errors.upstream5xxHead", { status, host });
|
|
7291
|
+
const action = t("errors.upstream5xxActionRetry");
|
|
7292
|
+
return `${head}${action}`;
|
|
7293
|
+
}
|
|
7096
7294
|
function reasonPrefixFor(reason) {
|
|
7097
7295
|
if (reason === "aborted") return t("errors.reasonAborted");
|
|
7098
7296
|
if (reason === "context-guard") return t("errors.reasonContextGuard");
|
|
@@ -7205,6 +7403,56 @@ function shrinkOversizedToolResultsByTokens(messages, maxTokens) {
|
|
|
7205
7403
|
});
|
|
7206
7404
|
return { messages: out, healedCount, tokensSaved, charsSaved };
|
|
7207
7405
|
}
|
|
7406
|
+
function shrinkOversizedToolCallArgsByTokens(messages, maxTokens) {
|
|
7407
|
+
let healedCount = 0;
|
|
7408
|
+
let tokensSaved = 0;
|
|
7409
|
+
let charsSaved = 0;
|
|
7410
|
+
const out = messages.map((msg) => {
|
|
7411
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.tool_calls)) return msg;
|
|
7412
|
+
let changed = false;
|
|
7413
|
+
const newCalls = msg.tool_calls.map((call) => {
|
|
7414
|
+
const args = call.function?.arguments;
|
|
7415
|
+
if (typeof args !== "string" || args.length <= maxTokens) return call;
|
|
7416
|
+
const beforeTokens = countTokensBounded(args);
|
|
7417
|
+
if (beforeTokens <= maxTokens) return call;
|
|
7418
|
+
const shrunk = shrinkJsonLongStrings(args);
|
|
7419
|
+
const afterTokens = countTokens(shrunk);
|
|
7420
|
+
if (afterTokens >= beforeTokens) return call;
|
|
7421
|
+
changed = true;
|
|
7422
|
+
healedCount += 1;
|
|
7423
|
+
tokensSaved += beforeTokens - afterTokens;
|
|
7424
|
+
charsSaved += args.length - shrunk.length;
|
|
7425
|
+
return { ...call, function: { ...call.function, arguments: shrunk } };
|
|
7426
|
+
});
|
|
7427
|
+
if (!changed) return msg;
|
|
7428
|
+
return { ...msg, tool_calls: newCalls };
|
|
7429
|
+
});
|
|
7430
|
+
return { messages: out, healedCount, tokensSaved, charsSaved };
|
|
7431
|
+
}
|
|
7432
|
+
function shrinkJsonLongStrings(jsonStr) {
|
|
7433
|
+
let parsed;
|
|
7434
|
+
try {
|
|
7435
|
+
parsed = JSON.parse(jsonStr);
|
|
7436
|
+
} catch {
|
|
7437
|
+
const head = jsonStr.slice(0, 200);
|
|
7438
|
+
return `${head}\u2026[shrunk: ${jsonStr.length} chars, unparsed]`;
|
|
7439
|
+
}
|
|
7440
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7441
|
+
return jsonStr;
|
|
7442
|
+
}
|
|
7443
|
+
const LONG_THRESHOLD = 300;
|
|
7444
|
+
const input = parsed;
|
|
7445
|
+
const output = {};
|
|
7446
|
+
for (const [k, v] of Object.entries(input)) {
|
|
7447
|
+
if (typeof v === "string" && v.length > LONG_THRESHOLD) {
|
|
7448
|
+
const newlines = v.match(/\n/g)?.length ?? 0;
|
|
7449
|
+
output[k] = `[\u2026shrunk: ${v.length} chars, ${newlines} lines \u2014 tool already responded, see result]`;
|
|
7450
|
+
} else {
|
|
7451
|
+
output[k] = v;
|
|
7452
|
+
}
|
|
7453
|
+
}
|
|
7454
|
+
return JSON.stringify(output);
|
|
7455
|
+
}
|
|
7208
7456
|
|
|
7209
7457
|
// src/loop/healing.ts
|
|
7210
7458
|
var _stampSeq = 0;
|
|
@@ -7275,12 +7523,13 @@ function stampMissingReasoningForThinkingMode(messages, model) {
|
|
|
7275
7523
|
function healLoadedMessagesByTokens(messages, maxTokens) {
|
|
7276
7524
|
const shrunk = shrinkOversizedToolResultsByTokens(messages, maxTokens);
|
|
7277
7525
|
const paired = fixToolCallPairing(shrunk.messages);
|
|
7278
|
-
const
|
|
7526
|
+
const argsShrunk = shrinkOversizedToolCallArgsByTokens(paired.messages, maxTokens);
|
|
7527
|
+
const healedCount = shrunk.healedCount + argsShrunk.healedCount + paired.droppedAssistantCalls + paired.droppedStrayTools;
|
|
7279
7528
|
return {
|
|
7280
|
-
messages:
|
|
7529
|
+
messages: argsShrunk.messages,
|
|
7281
7530
|
healedCount,
|
|
7282
|
-
tokensSaved: shrunk.tokensSaved,
|
|
7283
|
-
charsSaved: shrunk.charsSaved
|
|
7531
|
+
tokensSaved: shrunk.tokensSaved + argsShrunk.tokensSaved,
|
|
7532
|
+
charsSaved: shrunk.charsSaved + argsShrunk.charsSaved
|
|
7284
7533
|
};
|
|
7285
7534
|
}
|
|
7286
7535
|
|
|
@@ -7299,6 +7548,112 @@ function* hookWarnings(outcomes, turn) {
|
|
|
7299
7548
|
}
|
|
7300
7549
|
}
|
|
7301
7550
|
|
|
7551
|
+
// src/loop/reasoning-retention.ts
|
|
7552
|
+
function hasToolCalls(msg) {
|
|
7553
|
+
return Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
|
|
7554
|
+
}
|
|
7555
|
+
function stripDroppableReasoningContent(messages) {
|
|
7556
|
+
let lastUser = -1;
|
|
7557
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
7558
|
+
if (messages[i].role === "user") {
|
|
7559
|
+
lastUser = i;
|
|
7560
|
+
break;
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
if (lastUser < 0) {
|
|
7564
|
+
return { messages, prunedCount: 0, charsDropped: 0 };
|
|
7565
|
+
}
|
|
7566
|
+
let next = null;
|
|
7567
|
+
let prunedCount = 0;
|
|
7568
|
+
let charsDropped = 0;
|
|
7569
|
+
for (let i = 0; i < messages.length; i++) {
|
|
7570
|
+
const msg = messages[i];
|
|
7571
|
+
if (msg.role !== "assistant" || i > lastUser || hasToolCalls(msg) || !Object.hasOwn(msg, "reasoning_content")) {
|
|
7572
|
+
continue;
|
|
7573
|
+
}
|
|
7574
|
+
if (next === null) next = messages.slice();
|
|
7575
|
+
const { reasoning_content: dropped, ...replacement } = msg;
|
|
7576
|
+
if (typeof dropped === "string") charsDropped += dropped.length;
|
|
7577
|
+
next[i] = replacement;
|
|
7578
|
+
prunedCount += 1;
|
|
7579
|
+
}
|
|
7580
|
+
return {
|
|
7581
|
+
messages: next ?? messages,
|
|
7582
|
+
prunedCount,
|
|
7583
|
+
charsDropped
|
|
7584
|
+
};
|
|
7585
|
+
}
|
|
7586
|
+
|
|
7587
|
+
// src/loop/streaming.ts
|
|
7588
|
+
async function* streamModelResponse(opts) {
|
|
7589
|
+
const { client, model, messages, toolSpecs, signal, reasoningEffort, turn } = opts;
|
|
7590
|
+
let assistantContent = "";
|
|
7591
|
+
let reasoningContent = "";
|
|
7592
|
+
let usage = null;
|
|
7593
|
+
const callBuf = /* @__PURE__ */ new Map();
|
|
7594
|
+
const readyIndices = /* @__PURE__ */ new Set();
|
|
7595
|
+
for await (const chunk of client.stream({
|
|
7596
|
+
model,
|
|
7597
|
+
messages,
|
|
7598
|
+
tools: toolSpecs.length ? toolSpecs : void 0,
|
|
7599
|
+
signal,
|
|
7600
|
+
thinking: thinkingModeForModel(model),
|
|
7601
|
+
reasoningEffort
|
|
7602
|
+
})) {
|
|
7603
|
+
if (chunk.reasoningDelta) {
|
|
7604
|
+
reasoningContent += chunk.reasoningDelta;
|
|
7605
|
+
yield {
|
|
7606
|
+
turn,
|
|
7607
|
+
role: "assistant_delta",
|
|
7608
|
+
content: "",
|
|
7609
|
+
reasoningDelta: chunk.reasoningDelta
|
|
7610
|
+
};
|
|
7611
|
+
}
|
|
7612
|
+
if (chunk.contentDelta) {
|
|
7613
|
+
assistantContent += chunk.contentDelta;
|
|
7614
|
+
yield {
|
|
7615
|
+
turn,
|
|
7616
|
+
role: "assistant_delta",
|
|
7617
|
+
content: chunk.contentDelta
|
|
7618
|
+
};
|
|
7619
|
+
}
|
|
7620
|
+
if (chunk.toolCallDelta) {
|
|
7621
|
+
const d = chunk.toolCallDelta;
|
|
7622
|
+
const cur = callBuf.get(d.index) ?? {
|
|
7623
|
+
id: d.id,
|
|
7624
|
+
type: "function",
|
|
7625
|
+
function: { name: "", arguments: "" }
|
|
7626
|
+
};
|
|
7627
|
+
if (d.id) cur.id = d.id;
|
|
7628
|
+
if (d.name) cur.function.name = (cur.function.name ?? "") + d.name;
|
|
7629
|
+
if (d.argumentsDelta)
|
|
7630
|
+
cur.function.arguments = (cur.function.arguments ?? "") + d.argumentsDelta;
|
|
7631
|
+
callBuf.set(d.index, cur);
|
|
7632
|
+
if (!readyIndices.has(d.index) && cur.function.name && looksLikeCompleteJson(cur.function.arguments ?? "")) {
|
|
7633
|
+
readyIndices.add(d.index);
|
|
7634
|
+
}
|
|
7635
|
+
if (cur.function.name) {
|
|
7636
|
+
yield {
|
|
7637
|
+
turn,
|
|
7638
|
+
role: "tool_call_delta",
|
|
7639
|
+
content: "",
|
|
7640
|
+
toolName: cur.function.name,
|
|
7641
|
+
toolCallArgsChars: (cur.function.arguments ?? "").length,
|
|
7642
|
+
toolCallIndex: d.index,
|
|
7643
|
+
toolCallReadyCount: readyIndices.size
|
|
7644
|
+
};
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7647
|
+
if (chunk.usage) usage = chunk.usage;
|
|
7648
|
+
}
|
|
7649
|
+
return {
|
|
7650
|
+
assistantContent,
|
|
7651
|
+
reasoningContent,
|
|
7652
|
+
toolCalls: [...callBuf.values()],
|
|
7653
|
+
usage
|
|
7654
|
+
};
|
|
7655
|
+
}
|
|
7656
|
+
|
|
7302
7657
|
// src/repair/scavenge.ts
|
|
7303
7658
|
var MAX_SCAVENGE_INPUT = 100 * 1024;
|
|
7304
7659
|
function scavengeToolCalls(reasoningContent, opts) {
|
|
@@ -7656,6 +8011,10 @@ var MID_TURN_STEER_WRAPPER = "[Mid-turn steer queued by the user. Do not treat t
|
|
|
7656
8011
|
function formatSteerUserMessage(content) {
|
|
7657
8012
|
return [MID_TURN_STEER_WRAPPER, content].join("\n");
|
|
7658
8013
|
}
|
|
8014
|
+
function shrinkMessageForRetention(message) {
|
|
8015
|
+
if (message.role !== "assistant" || !Array.isArray(message.tool_calls)) return message;
|
|
8016
|
+
return shrinkOversizedToolCallArgsByTokens([message], DEFAULT_MAX_RESULT_TOKENS).messages[0] ?? message;
|
|
8017
|
+
}
|
|
7659
8018
|
var CacheFirstLoop = class {
|
|
7660
8019
|
client;
|
|
7661
8020
|
prefix;
|
|
@@ -7749,7 +8108,8 @@ var CacheFirstLoop = class {
|
|
|
7749
8108
|
const prior = loadSessionMessages(this.sessionName);
|
|
7750
8109
|
const shrunk = healLoadedMessagesByTokens(prior, DEFAULT_MAX_RESULT_TOKENS);
|
|
7751
8110
|
const stamped = stampMissingReasoningForThinkingMode(shrunk.messages, this.model);
|
|
7752
|
-
const
|
|
8111
|
+
const pruned = stripDroppableReasoningContent(stamped.messages);
|
|
8112
|
+
const messages = pruned.messages;
|
|
7753
8113
|
const healedCount = shrunk.healedCount + stamped.stampedCount;
|
|
7754
8114
|
const tokensSaved = shrunk.tokensSaved;
|
|
7755
8115
|
for (const msg of messages) this.log.append(msg);
|
|
@@ -7766,15 +8126,17 @@ var CacheFirstLoop = class {
|
|
|
7766
8126
|
lastPromptTokens: meta.lastPromptTokens
|
|
7767
8127
|
});
|
|
7768
8128
|
}
|
|
7769
|
-
if (healedCount > 0) {
|
|
8129
|
+
if (healedCount > 0 || pruned.prunedCount > 0) {
|
|
7770
8130
|
try {
|
|
7771
8131
|
rewriteSession(this.sessionName, messages);
|
|
7772
8132
|
} catch {
|
|
7773
8133
|
}
|
|
7774
|
-
|
|
7775
|
-
|
|
8134
|
+
if (healedCount > 0) {
|
|
8135
|
+
process.stderr.write(
|
|
8136
|
+
`\u25B8 session "${this.sessionName}": healed ${healedCount} entr${healedCount === 1 ? "y" : "ies"}${tokensSaved > 0 ? ` (shrunk ${tokensSaved.toLocaleString()} tokens of oversized tool output/arguments)` : " (dropped dangling tool_calls tail)"}. Rewrote session file.
|
|
7776
8137
|
`
|
|
7777
|
-
|
|
8138
|
+
);
|
|
8139
|
+
}
|
|
7778
8140
|
}
|
|
7779
8141
|
} else {
|
|
7780
8142
|
this.resumedMessageCount = 0;
|
|
@@ -7801,21 +8163,23 @@ var CacheFirstLoop = class {
|
|
|
7801
8163
|
return this.context.getLogTokens();
|
|
7802
8164
|
}
|
|
7803
8165
|
appendAndPersist(message) {
|
|
7804
|
-
|
|
8166
|
+
const retained = shrinkMessageForRetention(message);
|
|
8167
|
+
this.log.append(retained);
|
|
7805
8168
|
if (this.sessionName) {
|
|
7806
8169
|
try {
|
|
7807
|
-
appendSessionMessage(this.sessionName,
|
|
8170
|
+
appendSessionMessage(this.sessionName, retained);
|
|
7808
8171
|
} catch {
|
|
7809
8172
|
}
|
|
7810
8173
|
}
|
|
7811
8174
|
}
|
|
7812
8175
|
/** Swap the just-appended assistant entry — used by self-correction to restore the original tool_calls without dropping reasoning_content. */
|
|
7813
8176
|
replaceTailAssistantMessage(message) {
|
|
8177
|
+
const retained = shrinkMessageForRetention(message);
|
|
7814
8178
|
const entries = this.log.entries;
|
|
7815
8179
|
const tail = entries[entries.length - 1];
|
|
7816
8180
|
if (!tail || tail.role !== "assistant") return;
|
|
7817
8181
|
const kept = entries.slice(0, -1);
|
|
7818
|
-
kept.push(
|
|
8182
|
+
kept.push(retained);
|
|
7819
8183
|
this.log.compactInPlace(kept);
|
|
7820
8184
|
if (this.sessionName) {
|
|
7821
8185
|
try {
|
|
@@ -7841,6 +8205,8 @@ var CacheFirstLoop = class {
|
|
|
7841
8205
|
this.stats.reset();
|
|
7842
8206
|
this._turn = 0;
|
|
7843
8207
|
this._budgetWarned = false;
|
|
8208
|
+
this._steerQueue.length = 0;
|
|
8209
|
+
this._steerConsumed = false;
|
|
7844
8210
|
let systemRebuilt = false;
|
|
7845
8211
|
if (this._rebuildSystem) {
|
|
7846
8212
|
try {
|
|
@@ -7864,6 +8230,8 @@ var CacheFirstLoop = class {
|
|
|
7864
8230
|
this.log.compactInPlace([]);
|
|
7865
8231
|
this.scratch.reset();
|
|
7866
8232
|
this._inflight.clear();
|
|
8233
|
+
this._steerQueue.length = 0;
|
|
8234
|
+
this._steerConsumed = false;
|
|
7867
8235
|
this.sessionName = opts.sessionName;
|
|
7868
8236
|
if (this._rebuildSystem) {
|
|
7869
8237
|
try {
|
|
@@ -7941,7 +8309,8 @@ ${reason}`
|
|
|
7941
8309
|
signal,
|
|
7942
8310
|
maxResultTokens: DEFAULT_MAX_RESULT_TOKENS,
|
|
7943
8311
|
confirmationGate: this.confirmationGate,
|
|
7944
|
-
readTracker: this.readTracker
|
|
8312
|
+
readTracker: this.readTracker,
|
|
8313
|
+
rootDir: this.hookCwd
|
|
7945
8314
|
});
|
|
7946
8315
|
const postReport = await runHooks({
|
|
7947
8316
|
hooks: this.hooks,
|
|
@@ -7976,15 +8345,22 @@ ${reason}`
|
|
|
7976
8345
|
healActiveLogBeforeSend() {
|
|
7977
8346
|
const current = this.log.toMessages();
|
|
7978
8347
|
const healed = healLoadedMessages(current, DEFAULT_MAX_RESULT_CHARS);
|
|
7979
|
-
|
|
7980
|
-
|
|
8348
|
+
const argsShrunk = shrinkOversizedToolCallArgsByTokens(
|
|
8349
|
+
healed.messages,
|
|
8350
|
+
DEFAULT_MAX_RESULT_TOKENS
|
|
8351
|
+
);
|
|
8352
|
+
const pruned = stripDroppableReasoningContent(argsShrunk.messages);
|
|
8353
|
+
if (healed.healedCount === 0 && argsShrunk.healedCount === 0 && pruned.prunedCount === 0) {
|
|
8354
|
+
return current;
|
|
8355
|
+
}
|
|
8356
|
+
this.log.compactInPlace(pruned.messages);
|
|
7981
8357
|
if (this.sessionName) {
|
|
7982
8358
|
try {
|
|
7983
|
-
rewriteSession(this.sessionName,
|
|
8359
|
+
rewriteSession(this.sessionName, pruned.messages);
|
|
7984
8360
|
} catch {
|
|
7985
8361
|
}
|
|
7986
8362
|
}
|
|
7987
|
-
return
|
|
8363
|
+
return pruned.messages;
|
|
7988
8364
|
}
|
|
7989
8365
|
abort(opts = {}) {
|
|
7990
8366
|
if (opts.discardCurrentTurn) this._discardAbortRequested = true;
|
|
@@ -8094,7 +8470,7 @@ ${reason}`
|
|
|
8094
8470
|
const turnStartLogIndex = this.log.length;
|
|
8095
8471
|
this.appendAndPersist({ role: "user", content: userInput });
|
|
8096
8472
|
const toolSpecs = this.prefix.tools();
|
|
8097
|
-
|
|
8473
|
+
const rateLimitState = { shown: false };
|
|
8098
8474
|
{
|
|
8099
8475
|
const turnStart = this.context.estimateTurnStart(
|
|
8100
8476
|
this.buildMessages(),
|
|
@@ -8107,7 +8483,9 @@ ${reason}`
|
|
|
8107
8483
|
role: "status",
|
|
8108
8484
|
content: t("loop.turnStartFoldStatus")
|
|
8109
8485
|
};
|
|
8110
|
-
const result = await this.context.fold(this.model, {
|
|
8486
|
+
const result = await this.context.fold(this.model, {
|
|
8487
|
+
requireTailBoundary: true
|
|
8488
|
+
});
|
|
8111
8489
|
if (result.folded) {
|
|
8112
8490
|
this._foldedThisTurn = true;
|
|
8113
8491
|
yield {
|
|
@@ -8175,64 +8553,19 @@ ${reason}`
|
|
|
8175
8553
|
let usage = null;
|
|
8176
8554
|
try {
|
|
8177
8555
|
if (this.stream) {
|
|
8178
|
-
const
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
for await (const chunk of this.client.stream({
|
|
8182
|
-
model: callModel,
|
|
8556
|
+
const result = yield* streamModelResponse({
|
|
8557
|
+
client: this.client,
|
|
8558
|
+
model: this.model,
|
|
8183
8559
|
messages,
|
|
8184
|
-
|
|
8560
|
+
toolSpecs,
|
|
8185
8561
|
signal,
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
})
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
role: "assistant_delta",
|
|
8194
|
-
content: "",
|
|
8195
|
-
reasoningDelta: chunk.reasoningDelta
|
|
8196
|
-
};
|
|
8197
|
-
}
|
|
8198
|
-
if (chunk.contentDelta) {
|
|
8199
|
-
assistantContent += chunk.contentDelta;
|
|
8200
|
-
yield {
|
|
8201
|
-
turn: this._turn,
|
|
8202
|
-
role: "assistant_delta",
|
|
8203
|
-
content: chunk.contentDelta
|
|
8204
|
-
};
|
|
8205
|
-
}
|
|
8206
|
-
if (chunk.toolCallDelta) {
|
|
8207
|
-
const d = chunk.toolCallDelta;
|
|
8208
|
-
const cur = callBuf.get(d.index) ?? {
|
|
8209
|
-
id: d.id,
|
|
8210
|
-
type: "function",
|
|
8211
|
-
function: { name: "", arguments: "" }
|
|
8212
|
-
};
|
|
8213
|
-
if (d.id) cur.id = d.id;
|
|
8214
|
-
if (d.name) cur.function.name = (cur.function.name ?? "") + d.name;
|
|
8215
|
-
if (d.argumentsDelta)
|
|
8216
|
-
cur.function.arguments = (cur.function.arguments ?? "") + d.argumentsDelta;
|
|
8217
|
-
callBuf.set(d.index, cur);
|
|
8218
|
-
if (!readyIndices.has(d.index) && cur.function.name && looksLikeCompleteJson(cur.function.arguments ?? "")) {
|
|
8219
|
-
readyIndices.add(d.index);
|
|
8220
|
-
}
|
|
8221
|
-
if (cur.function.name) {
|
|
8222
|
-
yield {
|
|
8223
|
-
turn: this._turn,
|
|
8224
|
-
role: "tool_call_delta",
|
|
8225
|
-
content: "",
|
|
8226
|
-
toolName: cur.function.name,
|
|
8227
|
-
toolCallArgsChars: (cur.function.arguments ?? "").length,
|
|
8228
|
-
toolCallIndex: d.index,
|
|
8229
|
-
toolCallReadyCount: readyIndices.size
|
|
8230
|
-
};
|
|
8231
|
-
}
|
|
8232
|
-
}
|
|
8233
|
-
if (chunk.usage) usage = chunk.usage;
|
|
8234
|
-
}
|
|
8235
|
-
toolCalls = [...callBuf.values()];
|
|
8562
|
+
reasoningEffort: this.reasoningEffort,
|
|
8563
|
+
turn: this._turn
|
|
8564
|
+
});
|
|
8565
|
+
assistantContent = result.assistantContent;
|
|
8566
|
+
reasoningContent = result.reasoningContent;
|
|
8567
|
+
toolCalls = result.toolCalls;
|
|
8568
|
+
usage = result.usage;
|
|
8236
8569
|
} else {
|
|
8237
8570
|
const callModel = this.model;
|
|
8238
8571
|
const resp = await this.client.chat({
|
|
@@ -8259,12 +8592,14 @@ ${reason}`
|
|
|
8259
8592
|
this._steerQueue.length = 0;
|
|
8260
8593
|
return;
|
|
8261
8594
|
}
|
|
8262
|
-
const
|
|
8595
|
+
const upstreamHost = this.client.baseUrl;
|
|
8596
|
+
const dsHost = isDeepSeekHost(upstreamHost);
|
|
8597
|
+
const probe = is5xxError(err) && dsHost ? await probeDeepSeekReachable(this.client) : void 0;
|
|
8263
8598
|
yield {
|
|
8264
8599
|
turn: this._turn,
|
|
8265
8600
|
role: "error",
|
|
8266
8601
|
content: "",
|
|
8267
|
-
error: formatLoopError(err, probe)
|
|
8602
|
+
error: formatLoopError(err, probe, { upstreamHost })
|
|
8268
8603
|
};
|
|
8269
8604
|
this._steerQueue.length = 0;
|
|
8270
8605
|
return;
|
|
@@ -8390,76 +8725,16 @@ ${reason}`
|
|
|
8390
8725
|
this._steerQueue.length = 0;
|
|
8391
8726
|
return;
|
|
8392
8727
|
}
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
}
|
|
8404
|
-
if (chunk.length === 0) {
|
|
8405
|
-
chunk.push(repairedCalls[callIdx++]);
|
|
8406
|
-
}
|
|
8407
|
-
for (const call of chunk) {
|
|
8408
|
-
const callId = this.inflightIdFor(call);
|
|
8409
|
-
this._inflight.add(callId);
|
|
8410
|
-
yield {
|
|
8411
|
-
turn: this._turn,
|
|
8412
|
-
role: "tool_start",
|
|
8413
|
-
content: "",
|
|
8414
|
-
toolName: call.function?.name ?? "",
|
|
8415
|
-
toolArgs: call.function?.arguments ?? "{}",
|
|
8416
|
-
callId
|
|
8417
|
-
};
|
|
8418
|
-
}
|
|
8419
|
-
const settled = await Promise.allSettled(chunk.map((c) => this.runOneToolCall(c, signal)));
|
|
8420
|
-
for (let k = 0; k < chunk.length; k++) {
|
|
8421
|
-
const call = chunk[k];
|
|
8422
|
-
const name = call.function?.name ?? "";
|
|
8423
|
-
const args = call.function?.arguments ?? "{}";
|
|
8424
|
-
const s = settled[k];
|
|
8425
|
-
let result;
|
|
8426
|
-
let preWarnings = [];
|
|
8427
|
-
let postWarnings = [];
|
|
8428
|
-
if (s.status === "fulfilled") {
|
|
8429
|
-
preWarnings = s.value.preWarnings;
|
|
8430
|
-
postWarnings = s.value.postWarnings;
|
|
8431
|
-
result = s.value.result;
|
|
8432
|
-
} else {
|
|
8433
|
-
const err = s.reason instanceof Error ? s.reason : new Error(String(s.reason));
|
|
8434
|
-
result = JSON.stringify({ error: `${err.name}: ${err.message}` });
|
|
8435
|
-
}
|
|
8436
|
-
for (const w of preWarnings) yield w;
|
|
8437
|
-
for (const w of postWarnings) yield w;
|
|
8438
|
-
const rateLimited = parseRateLimitedToolResult(result);
|
|
8439
|
-
if (rateLimited && !rateLimitWarningShown) {
|
|
8440
|
-
rateLimitWarningShown = true;
|
|
8441
|
-
yield {
|
|
8442
|
-
turn: this._turn,
|
|
8443
|
-
role: "warning",
|
|
8444
|
-
content: rateLimited.message
|
|
8445
|
-
};
|
|
8446
|
-
}
|
|
8447
|
-
this.appendAndPersist({
|
|
8448
|
-
role: "tool",
|
|
8449
|
-
tool_call_id: call.id ?? "",
|
|
8450
|
-
name,
|
|
8451
|
-
content: result
|
|
8452
|
-
});
|
|
8453
|
-
yield {
|
|
8454
|
-
turn: this._turn,
|
|
8455
|
-
role: "tool",
|
|
8456
|
-
content: result,
|
|
8457
|
-
toolName: name,
|
|
8458
|
-
toolArgs: args,
|
|
8459
|
-
callId: this.inflightIdFor(call)
|
|
8460
|
-
};
|
|
8461
|
-
}
|
|
8462
|
-
}
|
|
8728
|
+
yield* dispatchToolCallsChunked(repairedCalls, {
|
|
8729
|
+
turn: this._turn,
|
|
8730
|
+
signal,
|
|
8731
|
+
isParallelSafe: (name) => this.tools.isParallelSafe(name),
|
|
8732
|
+
inflightIdFor: (call) => this.inflightIdFor(call),
|
|
8733
|
+
inflightAdd: (id) => this._inflight.add(id),
|
|
8734
|
+
runOne: (call, sig) => this.runOneToolCall(call, sig),
|
|
8735
|
+
appendAndPersist: (m) => this.appendAndPersist(m),
|
|
8736
|
+
rateLimitState
|
|
8737
|
+
});
|
|
8463
8738
|
}
|
|
8464
8739
|
}
|
|
8465
8740
|
summaryContext() {
|
|
@@ -8489,9 +8764,9 @@ function parsePositiveIntEnv(raw) {
|
|
|
8489
8764
|
}
|
|
8490
8765
|
|
|
8491
8766
|
// src/at-mentions.ts
|
|
8492
|
-
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
8767
|
+
import { existsSync as existsSync2, readFileSync, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
8493
8768
|
import { readdir, stat } from "fs/promises";
|
|
8494
|
-
import { isAbsolute, join, relative, resolve as
|
|
8769
|
+
import { isAbsolute, join as join2, relative as relative2, resolve as resolve3 } from "path";
|
|
8495
8770
|
|
|
8496
8771
|
// src/at-mentions-url.ts
|
|
8497
8772
|
var AT_URL_PATTERN = /(?<=^|\s)@(https?:\/\/\S+)/g;
|
|
@@ -8622,7 +8897,7 @@ function listFilesSync(root, opts = {}) {
|
|
|
8622
8897
|
function listFilesWithStatsSync(root, opts = {}) {
|
|
8623
8898
|
const maxResults = Math.max(1, opts.maxResults ?? 2e3);
|
|
8624
8899
|
const ignoreDirs = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
|
|
8625
|
-
const rootAbs =
|
|
8900
|
+
const rootAbs = resolve3(root);
|
|
8626
8901
|
const respectGi = opts.respectGitignore !== false;
|
|
8627
8902
|
const out = [];
|
|
8628
8903
|
const walk2 = (dirAbs, dirRel, layers) => {
|
|
@@ -8634,7 +8909,7 @@ function listFilesWithStatsSync(root, opts = {}) {
|
|
|
8634
8909
|
}
|
|
8635
8910
|
let entries;
|
|
8636
8911
|
try {
|
|
8637
|
-
entries =
|
|
8912
|
+
entries = readdirSync2(dirAbs, { withFileTypes: true });
|
|
8638
8913
|
} catch {
|
|
8639
8914
|
return;
|
|
8640
8915
|
}
|
|
@@ -8642,7 +8917,7 @@ function listFilesWithStatsSync(root, opts = {}) {
|
|
|
8642
8917
|
for (const ent of entries) {
|
|
8643
8918
|
if (out.length >= maxResults) return;
|
|
8644
8919
|
const relPath = dirRel ? `${dirRel}/${ent.name}` : ent.name;
|
|
8645
|
-
const absPath =
|
|
8920
|
+
const absPath = join2(dirAbs, ent.name);
|
|
8646
8921
|
if (ent.isDirectory()) {
|
|
8647
8922
|
if (ent.name.startsWith(".") || ignoreDirs.has(ent.name)) continue;
|
|
8648
8923
|
if (ignoredByLayers(effectiveLayers, absPath, true)) continue;
|
|
@@ -8651,14 +8926,14 @@ function listFilesWithStatsSync(root, opts = {}) {
|
|
|
8651
8926
|
if (ignoredByLayers(effectiveLayers, absPath, false)) continue;
|
|
8652
8927
|
let mtimeMs = 0;
|
|
8653
8928
|
try {
|
|
8654
|
-
mtimeMs =
|
|
8929
|
+
mtimeMs = statSync2(absPath).mtimeMs;
|
|
8655
8930
|
} catch {
|
|
8656
8931
|
}
|
|
8657
8932
|
out.push({ path: relPath, mtimeMs });
|
|
8658
8933
|
} else if (ent.isSymbolicLink()) {
|
|
8659
8934
|
let target = null;
|
|
8660
8935
|
try {
|
|
8661
|
-
target =
|
|
8936
|
+
target = statSync2(absPath);
|
|
8662
8937
|
} catch {
|
|
8663
8938
|
continue;
|
|
8664
8939
|
}
|
|
@@ -8686,7 +8961,7 @@ async function listFilesWithStatsAsync(root, opts = {}) {
|
|
|
8686
8961
|
async function walkFilesStream(root, opts) {
|
|
8687
8962
|
const ignoreDirs = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
|
|
8688
8963
|
const respectGi = opts.respectGitignore !== false;
|
|
8689
|
-
const rootAbs =
|
|
8964
|
+
const rootAbs = resolve3(root);
|
|
8690
8965
|
const progressGap = Math.max(0, opts.progressIntervalMs ?? 100);
|
|
8691
8966
|
let scanned = 0;
|
|
8692
8967
|
let halted = false;
|
|
@@ -8722,7 +8997,7 @@ async function walkFilesStream(root, opts) {
|
|
|
8722
8997
|
const fileEnts = [];
|
|
8723
8998
|
for (const ent of entries) {
|
|
8724
8999
|
if (halted || opts.signal?.aborted) break;
|
|
8725
|
-
const absPath =
|
|
9000
|
+
const absPath = join2(dirAbs, ent.name);
|
|
8726
9001
|
if (ent.isDirectory()) {
|
|
8727
9002
|
if (ent.name.startsWith(".") || ignoreDirs.has(ent.name)) continue;
|
|
8728
9003
|
if (ignoredByLayers(effectiveLayers, absPath, true)) continue;
|
|
@@ -8745,10 +9020,10 @@ async function walkFilesStream(root, opts) {
|
|
|
8745
9020
|
return { scanned, cancelled: !!opts.signal?.aborted };
|
|
8746
9021
|
}
|
|
8747
9022
|
async function flushFiles(ents, dirAbs, dirRel, layers, emit) {
|
|
8748
|
-
const accepted = ents.filter((e) => !ignoredByLayers(layers,
|
|
9023
|
+
const accepted = ents.filter((e) => !ignoredByLayers(layers, join2(dirAbs, e.name), false));
|
|
8749
9024
|
const stats = await Promise.all(
|
|
8750
9025
|
accepted.map(
|
|
8751
|
-
(e) => stat(
|
|
9026
|
+
(e) => stat(join2(dirAbs, e.name)).then((s) => ({ mtimeMs: s.mtimeMs, isFile: s.isFile() })).catch(() => null)
|
|
8752
9027
|
)
|
|
8753
9028
|
);
|
|
8754
9029
|
for (let i = 0; i < accepted.length; i++) {
|
|
@@ -8761,13 +9036,17 @@ async function flushFiles(ents, dirAbs, dirRel, layers, emit) {
|
|
|
8761
9036
|
});
|
|
8762
9037
|
}
|
|
8763
9038
|
}
|
|
9039
|
+
var listDirectoryCache = new TtlLruCache(64, 5e3);
|
|
8764
9040
|
async function listDirectory(root, relDir, opts = {}) {
|
|
8765
9041
|
const ignoreDirs = new Set(opts.ignoreDirs ?? DEFAULT_PICKER_IGNORE_DIRS);
|
|
8766
9042
|
const respectGi = opts.respectGitignore !== false;
|
|
8767
|
-
const rootAbs =
|
|
8768
|
-
const dirAbs =
|
|
8769
|
-
const rel =
|
|
9043
|
+
const rootAbs = resolve3(root);
|
|
9044
|
+
const dirAbs = resolve3(rootAbs, relDir);
|
|
9045
|
+
const rel = relative2(rootAbs, dirAbs);
|
|
8770
9046
|
if (rel.startsWith("..") || isAbsolute(rel)) return [];
|
|
9047
|
+
const cacheKey = `${dirAbs}\0${respectGi ? "g" : ""}\0${[...ignoreDirs].sort().join(",")}`;
|
|
9048
|
+
const cached = listDirectoryCache.get(cacheKey);
|
|
9049
|
+
if (cached) return cached;
|
|
8771
9050
|
const layers = [];
|
|
8772
9051
|
if (respectGi) {
|
|
8773
9052
|
const segs = rel ? rel.split(/[\\/]/) : [];
|
|
@@ -8775,7 +9054,7 @@ async function listDirectory(root, relDir, opts = {}) {
|
|
|
8775
9054
|
const ig = await loadGitignoreAt(cursor);
|
|
8776
9055
|
if (ig) layers.push({ dirAbs: cursor, ig });
|
|
8777
9056
|
for (const seg of segs) {
|
|
8778
|
-
cursor =
|
|
9057
|
+
cursor = join2(cursor, seg);
|
|
8779
9058
|
const igSeg = await loadGitignoreAt(cursor);
|
|
8780
9059
|
if (igSeg) layers.push({ dirAbs: cursor, ig: igSeg });
|
|
8781
9060
|
}
|
|
@@ -8790,7 +9069,7 @@ async function listDirectory(root, relDir, opts = {}) {
|
|
|
8790
9069
|
const dirs = [];
|
|
8791
9070
|
const files = [];
|
|
8792
9071
|
for (const ent of raw) {
|
|
8793
|
-
const absPath =
|
|
9072
|
+
const absPath = join2(dirAbs, ent.name);
|
|
8794
9073
|
if (ent.isDirectory()) {
|
|
8795
9074
|
if (ent.name.startsWith(".") || ignoreDirs.has(ent.name)) continue;
|
|
8796
9075
|
if (ignoredByLayers(layers, absPath, true)) continue;
|
|
@@ -8807,7 +9086,7 @@ async function listDirectory(root, relDir, opts = {}) {
|
|
|
8807
9086
|
}
|
|
8808
9087
|
const stats = await Promise.all(
|
|
8809
9088
|
files.map(
|
|
8810
|
-
(e) => stat(
|
|
9089
|
+
(e) => stat(join2(dirAbs, e.name)).then((s) => ({ mtimeMs: s.mtimeMs, isFile: s.isFile() })).catch(() => null)
|
|
8811
9090
|
)
|
|
8812
9091
|
);
|
|
8813
9092
|
const fileEntries = [];
|
|
@@ -8824,7 +9103,9 @@ async function listDirectory(root, relDir, opts = {}) {
|
|
|
8824
9103
|
}
|
|
8825
9104
|
dirs.sort((a, b) => a.name.localeCompare(b.name));
|
|
8826
9105
|
fileEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
8827
|
-
|
|
9106
|
+
const result = [...dirs, ...fileEntries];
|
|
9107
|
+
listDirectoryCache.set(cacheKey, result);
|
|
9108
|
+
return result;
|
|
8828
9109
|
}
|
|
8829
9110
|
function parseAtQuery(query) {
|
|
8830
9111
|
const normalized = query.replace(/\\/g, "/");
|
|
@@ -8930,7 +9211,7 @@ function expandAtMentions(text, rootDir, opts = {}) {
|
|
|
8930
9211
|
const maxBytes = opts.maxBytes ?? DEFAULT_AT_MENTION_MAX_BYTES;
|
|
8931
9212
|
const maxDirEntries = Math.max(1, opts.maxDirEntries ?? DEFAULT_AT_DIR_MAX_ENTRIES);
|
|
8932
9213
|
const fs4 = opts.fs ?? defaultFs;
|
|
8933
|
-
const root =
|
|
9214
|
+
const root = resolve3(rootDir);
|
|
8934
9215
|
const seen = /* @__PURE__ */ new Map();
|
|
8935
9216
|
const expansions = [];
|
|
8936
9217
|
const dirListings = /* @__PURE__ */ new Map();
|
|
@@ -8977,8 +9258,8 @@ function resolveMention(rawPath, root, maxBytes, maxDirEntries, fs4, dirListings
|
|
|
8977
9258
|
if (isAbsolute(rawPath)) {
|
|
8978
9259
|
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "escape" };
|
|
8979
9260
|
}
|
|
8980
|
-
const resolved =
|
|
8981
|
-
const rel =
|
|
9261
|
+
const resolved = resolve3(root, rawPath);
|
|
9262
|
+
const rel = relative2(root, resolved);
|
|
8982
9263
|
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
8983
9264
|
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "escape" };
|
|
8984
9265
|
}
|
|
@@ -9007,7 +9288,7 @@ function resolveMention(rawPath, root, maxBytes, maxDirEntries, fs4, dirListings
|
|
|
9007
9288
|
return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "not-file" };
|
|
9008
9289
|
}
|
|
9009
9290
|
function readSafe(root, rawPath, fs4) {
|
|
9010
|
-
const resolved =
|
|
9291
|
+
const resolved = resolve3(root, rawPath);
|
|
9011
9292
|
try {
|
|
9012
9293
|
return fs4.read(resolved);
|
|
9013
9294
|
} catch {
|
|
@@ -9015,23 +9296,23 @@ function readSafe(root, rawPath, fs4) {
|
|
|
9015
9296
|
}
|
|
9016
9297
|
}
|
|
9017
9298
|
var defaultFs = {
|
|
9018
|
-
exists: (p) =>
|
|
9299
|
+
exists: (p) => existsSync2(p),
|
|
9019
9300
|
isFile: (p) => {
|
|
9020
9301
|
try {
|
|
9021
|
-
return
|
|
9302
|
+
return statSync2(p).isFile();
|
|
9022
9303
|
} catch {
|
|
9023
9304
|
return false;
|
|
9024
9305
|
}
|
|
9025
9306
|
},
|
|
9026
9307
|
isDir: (p) => {
|
|
9027
9308
|
try {
|
|
9028
|
-
return
|
|
9309
|
+
return statSync2(p).isDirectory();
|
|
9029
9310
|
} catch {
|
|
9030
9311
|
return false;
|
|
9031
9312
|
}
|
|
9032
9313
|
},
|
|
9033
9314
|
listDir: (dirAbs, root, max) => {
|
|
9034
|
-
const dirRel =
|
|
9315
|
+
const dirRel = relative2(root, dirAbs).split(/[\\/]/).join("/");
|
|
9035
9316
|
const walkCap = Math.max(max * 4, 5e3);
|
|
9036
9317
|
const all = listFilesSync(root, { maxResults: walkCap });
|
|
9037
9318
|
const prefix = dirRel ? `${dirRel}/` : "";
|
|
@@ -9043,7 +9324,7 @@ var defaultFs = {
|
|
|
9043
9324
|
},
|
|
9044
9325
|
size: (p) => {
|
|
9045
9326
|
try {
|
|
9046
|
-
return
|
|
9327
|
+
return statSync2(p).size;
|
|
9047
9328
|
} catch {
|
|
9048
9329
|
return 0;
|
|
9049
9330
|
}
|
|
@@ -9976,21 +10257,21 @@ import { promises as fs3 } from "fs";
|
|
|
9976
10257
|
import * as pathMod5 from "path";
|
|
9977
10258
|
|
|
9978
10259
|
// src/memory/subdir.ts
|
|
9979
|
-
import { existsSync as
|
|
9980
|
-
import { dirname, join as
|
|
10260
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
10261
|
+
import { dirname, join as join3, relative as relative3, resolve as resolve4 } from "path";
|
|
9981
10262
|
function findDirMemory(absDir, rootDir) {
|
|
9982
|
-
const root =
|
|
9983
|
-
const target =
|
|
9984
|
-
const rel =
|
|
10263
|
+
const root = resolve4(rootDir);
|
|
10264
|
+
const target = resolve4(absDir);
|
|
10265
|
+
const rel = relative3(root, target);
|
|
9985
10266
|
if (rel.startsWith("..")) return [];
|
|
9986
10267
|
const found = [];
|
|
9987
10268
|
let cur = target;
|
|
9988
10269
|
while (cur !== root) {
|
|
9989
|
-
const r =
|
|
10270
|
+
const r = relative3(root, cur);
|
|
9990
10271
|
if (!r || r.startsWith("..")) break;
|
|
9991
10272
|
for (const name of PROJECT_MEMORY_FILES) {
|
|
9992
|
-
const path =
|
|
9993
|
-
if (
|
|
10273
|
+
const path = join3(cur, name);
|
|
10274
|
+
if (existsSync3(path)) {
|
|
9994
10275
|
found.push(path);
|
|
9995
10276
|
break;
|
|
9996
10277
|
}
|
|
@@ -10002,7 +10283,7 @@ function findDirMemory(absDir, rootDir) {
|
|
|
10002
10283
|
return found;
|
|
10003
10284
|
}
|
|
10004
10285
|
function findSubdirMemoryAncestors(absPath, rootDir) {
|
|
10005
|
-
return findDirMemory(dirname(
|
|
10286
|
+
return findDirMemory(dirname(resolve4(absPath)), rootDir);
|
|
10006
10287
|
}
|
|
10007
10288
|
function readSubdirMemoryContent(path) {
|
|
10008
10289
|
let raw;
|
|
@@ -10304,7 +10585,7 @@ var RegexRunner = class {
|
|
|
10304
10585
|
this.defaultTimeoutMs = opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
10305
10586
|
}
|
|
10306
10587
|
testLines(text, source, flags, opts = {}) {
|
|
10307
|
-
return new Promise((
|
|
10588
|
+
return new Promise((resolve7, reject) => {
|
|
10308
10589
|
if (opts.signal?.aborted) {
|
|
10309
10590
|
reject(new Error("regex evaluation aborted"));
|
|
10310
10591
|
return;
|
|
@@ -10317,7 +10598,7 @@ var RegexRunner = class {
|
|
|
10317
10598
|
this.killWorker();
|
|
10318
10599
|
reject(new Error(`regex evaluation exceeded ${timeoutMs}ms`));
|
|
10319
10600
|
}, timeoutMs);
|
|
10320
|
-
const entry = { resolve:
|
|
10601
|
+
const entry = { resolve: resolve7, reject, timer };
|
|
10321
10602
|
if (opts.signal) {
|
|
10322
10603
|
entry.signal = opts.signal;
|
|
10323
10604
|
entry.onAbort = () => {
|
|
@@ -10448,6 +10729,7 @@ async function searchFiles(ctx, startAbs, args) {
|
|
|
10448
10729
|
var MAX_HITS_PER_FILE = 30;
|
|
10449
10730
|
var SUMMARY_MODE_TRIGGER_RATIO = 0.8;
|
|
10450
10731
|
var WALK_DEADLINE_MS = 12e4;
|
|
10732
|
+
var REGEX_METACHARS = /[\\.+*?()[\]{}|^$]/;
|
|
10451
10733
|
async function searchContent(ctx, startAbs, args) {
|
|
10452
10734
|
throwIfAborted(args.signal);
|
|
10453
10735
|
const caseSensitive = args.case_sensitive === true;
|
|
@@ -10455,12 +10737,15 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10455
10737
|
const ctxLines = Math.max(0, Math.min(20, Math.floor(args.context ?? 0)));
|
|
10456
10738
|
const summaryOnly = args.summary_only === true;
|
|
10457
10739
|
const reFlags = caseSensitive ? "" : "i";
|
|
10740
|
+
const hasMeta = REGEX_METACHARS.test(args.pattern);
|
|
10458
10741
|
let reSource = null;
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10462
|
-
|
|
10463
|
-
|
|
10742
|
+
if (hasMeta) {
|
|
10743
|
+
try {
|
|
10744
|
+
new RegExp(args.pattern, reFlags);
|
|
10745
|
+
reSource = args.pattern;
|
|
10746
|
+
} catch {
|
|
10747
|
+
reSource = null;
|
|
10748
|
+
}
|
|
10464
10749
|
}
|
|
10465
10750
|
const needle = caseSensitive ? args.pattern : args.pattern.toLowerCase();
|
|
10466
10751
|
const matches = [];
|
|
@@ -10549,9 +10834,10 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10549
10834
|
if (firstNul !== -1 && firstNul < 8 * 1024) continue;
|
|
10550
10835
|
const text = raw.toString("utf8");
|
|
10551
10836
|
const rel = displayRel2(ctx.rootDir, full);
|
|
10552
|
-
const lines = text.split(/\r?\n/);
|
|
10553
10837
|
let hits;
|
|
10838
|
+
let lines;
|
|
10554
10839
|
if (reSource !== null) {
|
|
10840
|
+
lines = text.split(/\r?\n/);
|
|
10555
10841
|
try {
|
|
10556
10842
|
hits = await getRegexRunner().testLines(text, reSource, reFlags, {
|
|
10557
10843
|
signal: args.signal
|
|
@@ -10563,9 +10849,14 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10563
10849
|
continue;
|
|
10564
10850
|
}
|
|
10565
10851
|
} else {
|
|
10852
|
+
const haystack = caseSensitive ? text : text.toLowerCase();
|
|
10853
|
+
if (haystack.indexOf(needle) === -1) {
|
|
10854
|
+
scanned++;
|
|
10855
|
+
continue;
|
|
10856
|
+
}
|
|
10857
|
+
lines = text.split(/\r?\n/);
|
|
10566
10858
|
hits = [];
|
|
10567
10859
|
for (let li = 0; li < lines.length; li++) {
|
|
10568
|
-
throwIfAborted(args.signal);
|
|
10569
10860
|
const lineForCheck = caseSensitive ? lines[li] : lines[li].toLowerCase();
|
|
10570
10861
|
if (lineForCheck.includes(needle)) hits.push(li);
|
|
10571
10862
|
}
|
|
@@ -10773,6 +11064,7 @@ ${body}`;
|
|
|
10773
11064
|
registry.register({
|
|
10774
11065
|
name: "read_file",
|
|
10775
11066
|
parallelSafe: true,
|
|
11067
|
+
skipTruncationSave: true,
|
|
10776
11068
|
description: `Read a file under the sandbox root. Default returns FULL CONTENT for files \u2264 ${Math.round(DEFAULT_OUTLINE_THRESHOLD_BYTES / 1024)} KiB. Optional scoping: head/tail (N lines), range "A-B" (1-indexed inclusive). Larger files auto-switch to outline mode (metadata + head + symbol outline for TS/JS/Python/Go/Rust/Markdown/Protobuf/text) \u2014 drill in with range or search_content. Files over ${Math.round(HARD_MAX_FILE_BYTES / (1024 * 1024))} MiB and binaries are refused \u2014 use get_file_info for stat.`,
|
|
10777
11069
|
readOnly: true,
|
|
10778
11070
|
stormExempt: true,
|
|
@@ -10870,6 +11162,7 @@ ${slice.join("\n")}`);
|
|
|
10870
11162
|
registry.register({
|
|
10871
11163
|
name: "list_directory",
|
|
10872
11164
|
parallelSafe: true,
|
|
11165
|
+
skipTruncationSave: true,
|
|
10873
11166
|
description: "List entries in a directory under the sandbox root. Returns one line per entry, marking directories with a trailing slash. Not recursive \u2014 use directory_tree for that.",
|
|
10874
11167
|
readOnly: true,
|
|
10875
11168
|
stormExempt: true,
|
|
@@ -10892,6 +11185,7 @@ ${slice.join("\n")}`);
|
|
|
10892
11185
|
registry.register({
|
|
10893
11186
|
name: "directory_tree",
|
|
10894
11187
|
parallelSafe: true,
|
|
11188
|
+
skipTruncationSave: true,
|
|
10895
11189
|
description: `Recursively list entries with indented tree structure (dirs marked '/'). Budget-aware: maxDepth defaults to 2, large subtrees (>50 children) auto-collapse to "[N hidden \u2014 list_directory to inspect]", and ${[...SKIP_DIR_NAMES].sort().join(" / ")} are skipped unless include_deps:true. For single-level use list_directory; for path lookups use search_files; for code lookups use search_content.`,
|
|
10896
11190
|
readOnly: true,
|
|
10897
11191
|
parameters: {
|
|
@@ -10967,6 +11261,7 @@ ${slice.join("\n")}`);
|
|
|
10967
11261
|
registry.register({
|
|
10968
11262
|
name: "search_files",
|
|
10969
11263
|
parallelSafe: true,
|
|
11264
|
+
skipTruncationSave: true,
|
|
10970
11265
|
description: "Find files whose NAME matches a substring or regex. Case-insensitive. Walks the directory recursively under the sandbox root. Returns one path per line. Skips dependency / VCS / build directories (node_modules, .git, dist, build, .next, target, .venv) by default.",
|
|
10971
11266
|
readOnly: true,
|
|
10972
11267
|
parameters: {
|
|
@@ -10993,6 +11288,7 @@ ${slice.join("\n")}`);
|
|
|
10993
11288
|
registry.register({
|
|
10994
11289
|
name: "search_content",
|
|
10995
11290
|
parallelSafe: true,
|
|
11291
|
+
skipTruncationSave: true,
|
|
10996
11292
|
description: "Recursively grep file CONTENTS for a substring or regex \u2014 'where is X called', 'what files contain Y'. Returns one match per line as `path:line: text`. Per-file hit cap 30; when the byte budget is mostly spent, remaining files switch to a `rel: N matches` histogram. Pass `summary_only:true` for just the histogram. Skips dependency / VCS / build dirs and binary files. For file NAMES use search_files.",
|
|
10997
11293
|
readOnly: true,
|
|
10998
11294
|
parameters: {
|
|
@@ -11044,6 +11340,7 @@ ${slice.join("\n")}`);
|
|
|
11044
11340
|
registry.register({
|
|
11045
11341
|
name: "glob",
|
|
11046
11342
|
parallelSafe: true,
|
|
11343
|
+
skipTruncationSave: true,
|
|
11047
11344
|
description: "List files matching a glob pattern, sorted by mtime (most-recently-modified first) by default. Use this for 'what changed lately', 'find all *.test.ts', 'all configs under src/'. Glob syntax matches the cross-tool standard: `*` (any chars in one segment), `**` (any segments), `?` (one char), `{a,b}` (alternation). Pattern matches against the path RELATIVE to the search root (e.g. 'src/**/*.ts' from project root). Skips node_modules / .git / dist / build / etc by default. Default limit 200; raise via `limit` (max 1000). Different from `search_files` (substring on basename) and `search_content` (matches inside file contents).",
|
|
11048
11345
|
readOnly: true,
|
|
11049
11346
|
parameters: {
|
|
@@ -11082,6 +11379,7 @@ ${slice.join("\n")}`);
|
|
|
11082
11379
|
registry.register({
|
|
11083
11380
|
name: "get_file_info",
|
|
11084
11381
|
parallelSafe: true,
|
|
11382
|
+
skipTruncationSave: true,
|
|
11085
11383
|
description: "Stat a path under the sandbox root. Returns type (file|directory|symlink), size in bytes, mtime in ISO-8601.",
|
|
11086
11384
|
readOnly: true,
|
|
11087
11385
|
parameters: {
|
|
@@ -12017,19 +12315,22 @@ function forkRegistryWithAllowList(parent, allow, alsoExclude) {
|
|
|
12017
12315
|
|
|
12018
12316
|
// src/code/edit-blocks.ts
|
|
12019
12317
|
import {
|
|
12318
|
+
chmodSync as chmodSync2,
|
|
12020
12319
|
closeSync,
|
|
12021
|
-
existsSync as
|
|
12320
|
+
existsSync as existsSync4,
|
|
12022
12321
|
fstatSync,
|
|
12023
|
-
|
|
12024
|
-
mkdirSync,
|
|
12322
|
+
fsyncSync,
|
|
12323
|
+
mkdirSync as mkdirSync2,
|
|
12025
12324
|
openSync,
|
|
12026
12325
|
readFileSync as readFileSync3,
|
|
12027
12326
|
readSync,
|
|
12327
|
+
realpathSync,
|
|
12328
|
+
renameSync,
|
|
12028
12329
|
unlinkSync,
|
|
12029
|
-
writeFileSync,
|
|
12330
|
+
writeFileSync as writeFileSync2,
|
|
12030
12331
|
writeSync
|
|
12031
12332
|
} from "fs";
|
|
12032
|
-
import { dirname as dirname3, isAbsolute as isAbsolute3, relative as
|
|
12333
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, relative as relative7, resolve as resolve6 } from "path";
|
|
12033
12334
|
var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
|
|
12034
12335
|
function parseEditBlocks(text) {
|
|
12035
12336
|
const out = [];
|
|
@@ -12047,15 +12348,15 @@ function parseEditBlocks(text) {
|
|
|
12047
12348
|
return out;
|
|
12048
12349
|
}
|
|
12049
12350
|
function resolveEditPath(rootDir, rawPath) {
|
|
12050
|
-
const absRoot =
|
|
12351
|
+
const absRoot = resolve6(rootDir);
|
|
12051
12352
|
if (/^[A-Za-z]:[\\/]/.test(rawPath) || looksLikeAbsoluteSystemPath2(rawPath)) {
|
|
12052
|
-
return
|
|
12353
|
+
return resolve6(rawPath);
|
|
12053
12354
|
}
|
|
12054
12355
|
let rooted = rawPath;
|
|
12055
12356
|
while (rooted.startsWith("/") || rooted.startsWith("\\")) {
|
|
12056
12357
|
rooted = rooted.slice(1);
|
|
12057
12358
|
}
|
|
12058
|
-
return
|
|
12359
|
+
return resolve6(absRoot, rooted || ".");
|
|
12059
12360
|
}
|
|
12060
12361
|
function looksLikeAbsoluteSystemPath2(rawPath) {
|
|
12061
12362
|
return /^\/(?:home|Users|etc|var|opt|tmp|usr|mnt|Library|Volumes|proc|sys|dev|run|srv|media|Applications|System|root|boot|private)(?:[/\\]|$)/.test(
|
|
@@ -12063,11 +12364,59 @@ function looksLikeAbsoluteSystemPath2(rawPath) {
|
|
|
12063
12364
|
);
|
|
12064
12365
|
}
|
|
12065
12366
|
function pathIsUnder2(child, parent) {
|
|
12066
|
-
const rel =
|
|
12367
|
+
const rel = relative7(parent, child);
|
|
12067
12368
|
return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
|
|
12068
12369
|
}
|
|
12370
|
+
function writeAllSync(fd, buf) {
|
|
12371
|
+
let written = 0;
|
|
12372
|
+
while (written < buf.length) {
|
|
12373
|
+
const n = writeSync(fd, buf, written, buf.length - written, written);
|
|
12374
|
+
if (n <= 0) throw new Error("write returned 0 bytes before completing");
|
|
12375
|
+
written += n;
|
|
12376
|
+
}
|
|
12377
|
+
}
|
|
12378
|
+
function fsyncDirectoryBestEffort(path) {
|
|
12379
|
+
let fd;
|
|
12380
|
+
try {
|
|
12381
|
+
fd = openSync(path, "r");
|
|
12382
|
+
fsyncSync(fd);
|
|
12383
|
+
} catch {
|
|
12384
|
+
} finally {
|
|
12385
|
+
if (fd !== void 0) closeSync(fd);
|
|
12386
|
+
}
|
|
12387
|
+
}
|
|
12388
|
+
function atomicReplaceFileSync(path, buf, mode) {
|
|
12389
|
+
const tmp = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
12390
|
+
const permissions = mode & 4095;
|
|
12391
|
+
let fd;
|
|
12392
|
+
try {
|
|
12393
|
+
fd = openSync(tmp, "wx", permissions);
|
|
12394
|
+
writeAllSync(fd, buf);
|
|
12395
|
+
try {
|
|
12396
|
+
chmodSync2(tmp, permissions);
|
|
12397
|
+
} catch {
|
|
12398
|
+
}
|
|
12399
|
+
fsyncSync(fd);
|
|
12400
|
+
closeSync(fd);
|
|
12401
|
+
fd = void 0;
|
|
12402
|
+
renameSync(tmp, path);
|
|
12403
|
+
fsyncDirectoryBestEffort(dirname3(path));
|
|
12404
|
+
} catch (err) {
|
|
12405
|
+
if (fd !== void 0) {
|
|
12406
|
+
try {
|
|
12407
|
+
closeSync(fd);
|
|
12408
|
+
} catch {
|
|
12409
|
+
}
|
|
12410
|
+
}
|
|
12411
|
+
try {
|
|
12412
|
+
unlinkSync(tmp);
|
|
12413
|
+
} catch {
|
|
12414
|
+
}
|
|
12415
|
+
throw err;
|
|
12416
|
+
}
|
|
12417
|
+
}
|
|
12069
12418
|
function applyEditBlock(block, rootDir) {
|
|
12070
|
-
const absRoot =
|
|
12419
|
+
const absRoot = resolve6(rootDir);
|
|
12071
12420
|
const absTarget = resolveEditPath(rootDir, block.path);
|
|
12072
12421
|
if (!pathIsUnder2(absTarget, absRoot)) {
|
|
12073
12422
|
return {
|
|
@@ -12079,7 +12428,7 @@ function applyEditBlock(block, rootDir) {
|
|
|
12079
12428
|
const searchEmpty = block.search.length === 0;
|
|
12080
12429
|
if (searchEmpty) {
|
|
12081
12430
|
try {
|
|
12082
|
-
|
|
12431
|
+
mkdirSync2(dirname3(absTarget), { recursive: true });
|
|
12083
12432
|
const fd = openSync(absTarget, "wx");
|
|
12084
12433
|
try {
|
|
12085
12434
|
writeSync(fd, block.replace);
|
|
@@ -12100,9 +12449,22 @@ function applyEditBlock(block, rootDir) {
|
|
|
12100
12449
|
}
|
|
12101
12450
|
}
|
|
12102
12451
|
try {
|
|
12452
|
+
let writeTarget;
|
|
12453
|
+
try {
|
|
12454
|
+
writeTarget = realpathSync(absTarget);
|
|
12455
|
+
} catch (err) {
|
|
12456
|
+
if (err.code === "ENOENT") {
|
|
12457
|
+
return {
|
|
12458
|
+
path: block.path,
|
|
12459
|
+
status: "file-missing",
|
|
12460
|
+
message: "file does not exist; to create it, use an empty SEARCH block"
|
|
12461
|
+
};
|
|
12462
|
+
}
|
|
12463
|
+
throw err;
|
|
12464
|
+
}
|
|
12103
12465
|
let fd;
|
|
12104
12466
|
try {
|
|
12105
|
-
fd = openSync(
|
|
12467
|
+
fd = openSync(writeTarget, "r+");
|
|
12106
12468
|
} catch (err) {
|
|
12107
12469
|
if (err.code === "ENOENT") {
|
|
12108
12470
|
return {
|
|
@@ -12143,17 +12505,12 @@ function applyEditBlock(block, rootDir) {
|
|
|
12143
12505
|
};
|
|
12144
12506
|
}
|
|
12145
12507
|
const replaced = `${content.slice(0, idx)}${adaptedReplace}${content.slice(idx + adaptedSearch.length)}`;
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
while (written < outBuf.length) {
|
|
12150
|
-
const n = writeSync(fd, outBuf, written, outBuf.length - written, written);
|
|
12151
|
-
if (n <= 0) break;
|
|
12152
|
-
written += n;
|
|
12153
|
-
}
|
|
12508
|
+
closeSync(fd);
|
|
12509
|
+
fd = void 0;
|
|
12510
|
+
atomicReplaceFileSync(writeTarget, encodeFile(replaced, encoding), stat2.mode);
|
|
12154
12511
|
return { path: block.path, status: "applied" };
|
|
12155
12512
|
} finally {
|
|
12156
|
-
closeSync(fd);
|
|
12513
|
+
if (fd !== void 0) closeSync(fd);
|
|
12157
12514
|
}
|
|
12158
12515
|
} catch (err) {
|
|
12159
12516
|
return { path: block.path, status: "error", message: err.message };
|
|
@@ -12165,7 +12522,7 @@ function applyEditBlocks(blocks, rootDir) {
|
|
|
12165
12522
|
function toWholeFileEditBlock(path, content, rootDir) {
|
|
12166
12523
|
const abs = resolveEditPath(rootDir, path);
|
|
12167
12524
|
let search = "";
|
|
12168
|
-
if (
|
|
12525
|
+
if (existsSync4(abs)) {
|
|
12169
12526
|
try {
|
|
12170
12527
|
search = decodeFileBuffer(readFileSync3(abs)).text;
|
|
12171
12528
|
} catch {
|
|
@@ -12175,7 +12532,7 @@ function toWholeFileEditBlock(path, content, rootDir) {
|
|
|
12175
12532
|
return { path, search, replace: content, offset: 0 };
|
|
12176
12533
|
}
|
|
12177
12534
|
function snapshotBeforeEdits(blocks, rootDir) {
|
|
12178
|
-
const absRoot =
|
|
12535
|
+
const absRoot = resolve6(rootDir);
|
|
12179
12536
|
const seen = /* @__PURE__ */ new Set();
|
|
12180
12537
|
const snapshots = [];
|
|
12181
12538
|
for (const b of blocks) {
|
|
@@ -12183,7 +12540,7 @@ function snapshotBeforeEdits(blocks, rootDir) {
|
|
|
12183
12540
|
if (!pathIsUnder2(abs, absRoot)) continue;
|
|
12184
12541
|
if (seen.has(abs)) continue;
|
|
12185
12542
|
seen.add(abs);
|
|
12186
|
-
if (!
|
|
12543
|
+
if (!existsSync4(abs)) {
|
|
12187
12544
|
snapshots.push({ path: b.path, prevContent: null });
|
|
12188
12545
|
continue;
|
|
12189
12546
|
}
|
|
@@ -12197,7 +12554,7 @@ function snapshotBeforeEdits(blocks, rootDir) {
|
|
|
12197
12554
|
return snapshots;
|
|
12198
12555
|
}
|
|
12199
12556
|
function restoreSnapshots(snapshots, rootDir) {
|
|
12200
|
-
const absRoot =
|
|
12557
|
+
const absRoot = resolve6(rootDir);
|
|
12201
12558
|
return snapshots.map((snap) => {
|
|
12202
12559
|
const abs = resolveEditPath(rootDir, snap.path);
|
|
12203
12560
|
if (!pathIsUnder2(abs, absRoot)) {
|
|
@@ -12209,14 +12566,14 @@ function restoreSnapshots(snapshots, rootDir) {
|
|
|
12209
12566
|
}
|
|
12210
12567
|
try {
|
|
12211
12568
|
if (snap.prevContent === null) {
|
|
12212
|
-
if (
|
|
12569
|
+
if (existsSync4(abs)) unlinkSync(abs);
|
|
12213
12570
|
return {
|
|
12214
12571
|
path: snap.path,
|
|
12215
12572
|
status: "applied",
|
|
12216
12573
|
message: "removed (the edit had created it)"
|
|
12217
12574
|
};
|
|
12218
12575
|
}
|
|
12219
|
-
|
|
12576
|
+
writeFileSync2(abs, encodeFile(snap.prevContent, snap.prevEncoding ?? "utf8"));
|
|
12220
12577
|
return {
|
|
12221
12578
|
path: snap.path,
|
|
12222
12579
|
status: "applied",
|
|
@@ -12235,6 +12592,7 @@ export {
|
|
|
12235
12592
|
ToolRegistry,
|
|
12236
12593
|
registerSingleMcpTool,
|
|
12237
12594
|
bridgeMcpTools,
|
|
12595
|
+
isDeepSeekHost,
|
|
12238
12596
|
ImmutablePrefix,
|
|
12239
12597
|
CacheFirstLoop,
|
|
12240
12598
|
expandAtUrls,
|
|
@@ -12268,4 +12626,4 @@ export {
|
|
|
12268
12626
|
he/he.js:
|
|
12269
12627
|
(*! https://mths.be/he v1.2.0 by @mathias | MIT license *)
|
|
12270
12628
|
*/
|
|
12271
|
-
//# sourceMappingURL=chunk-
|
|
12629
|
+
//# sourceMappingURL=chunk-K4YQFULP.js.map
|