nexrall-code 0.5.114 → 0.5.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +467 -108
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3078,9 +3078,15 @@ var require_types = __commonJS({
|
|
|
3078
3078
|
"../core/dist/types.js"(exports2) {
|
|
3079
3079
|
"use strict";
|
|
3080
3080
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3081
|
-
exports2.AgentTurnError = void 0;
|
|
3081
|
+
exports2.AgentTurnError = exports2.RUNTIME_CONTEXT_OPEN_TAG = void 0;
|
|
3082
|
+
exports2.isRuntimeContextBlock = isRuntimeContextBlock;
|
|
3082
3083
|
exports2.isAgentTurnError = isAgentTurnError;
|
|
3083
3084
|
exports2.salvageHistory = salvageHistory2;
|
|
3085
|
+
exports2.RUNTIME_CONTEXT_OPEN_TAG = "<runtime_context>";
|
|
3086
|
+
function isRuntimeContextBlock(b) {
|
|
3087
|
+
const x2 = b;
|
|
3088
|
+
return !!x2 && x2.type === "text" && typeof x2.text === "string" && x2.text.startsWith(exports2.RUNTIME_CONTEXT_OPEN_TAG);
|
|
3089
|
+
}
|
|
3084
3090
|
var AgentTurnError = class extends Error {
|
|
3085
3091
|
constructor(message, messages, progressCount, cause) {
|
|
3086
3092
|
super(message);
|
|
@@ -9915,6 +9921,8 @@ var require_client = __commonJS({
|
|
|
9915
9921
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9916
9922
|
exports2.API_BASE = void 0;
|
|
9917
9923
|
exports2.chooseFinalContent = chooseFinalContent;
|
|
9924
|
+
exports2.earlyToolResolveEnabled = earlyToolResolveEnabled;
|
|
9925
|
+
exports2.gzipRequestsEnabled = gzipRequestsEnabled;
|
|
9918
9926
|
exports2.streamChat = streamChat;
|
|
9919
9927
|
exports2.cancelTurn = cancelTurn;
|
|
9920
9928
|
exports2.revokeRefreshToken = revokeRefreshToken2;
|
|
@@ -9931,6 +9939,7 @@ var require_client = __commonJS({
|
|
|
9931
9939
|
var eventsource_parser_1 = require_dist();
|
|
9932
9940
|
var node_fetch_1 = __importDefault((init_src(), __toCommonJS(src_exports)));
|
|
9933
9941
|
var crypto_1 = __require("crypto");
|
|
9942
|
+
var zlib_1 = __require("zlib");
|
|
9934
9943
|
var index_1 = require_auth();
|
|
9935
9944
|
var DEFAULT_API_BASE = "https://api.nexrall.com";
|
|
9936
9945
|
function resolveApiBase() {
|
|
@@ -10021,8 +10030,16 @@ var require_client = __commonJS({
|
|
|
10021
10030
|
var MAX_RETRIES = 5;
|
|
10022
10031
|
var RETRY_BASE_MS = 1e3;
|
|
10023
10032
|
var RETRY_MAX_MS = 3e4;
|
|
10033
|
+
function earlyToolResolveEnabled() {
|
|
10034
|
+
return process.env.NEXRALL_EARLY_TOOL_RESOLVE !== "0";
|
|
10035
|
+
}
|
|
10036
|
+
var GZIP_MIN_BYTES = 32 * 1024;
|
|
10037
|
+
function gzipRequestsEnabled() {
|
|
10038
|
+
return process.env.NEXRALL_GZIP_REQUESTS !== "0";
|
|
10039
|
+
}
|
|
10024
10040
|
var HOUSEKEEPING_FRAMES = /* @__PURE__ */ new Set([
|
|
10025
10041
|
"resumable",
|
|
10042
|
+
"runtime_context",
|
|
10026
10043
|
"context_warning",
|
|
10027
10044
|
"tool_progress"
|
|
10028
10045
|
]);
|
|
@@ -10094,6 +10111,14 @@ var require_client = __commonJS({
|
|
|
10094
10111
|
let carryToolUse = [];
|
|
10095
10112
|
let emittedAnythingAcrossAttempts = false;
|
|
10096
10113
|
let emittedCharsAcrossAttempts = 0;
|
|
10114
|
+
let chatBody = null;
|
|
10115
|
+
const getChatBody = () => {
|
|
10116
|
+
if (chatBody && chatBody.turnId === turnId)
|
|
10117
|
+
return chatBody;
|
|
10118
|
+
const json = JSON.stringify({ messages, model, env: env4, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb, toolAllowlist, ...billingOverrideFields2() });
|
|
10119
|
+
chatBody = gzipRequestsEnabled() && json.length >= GZIP_MIN_BYTES ? { data: (0, zlib_1.gzipSync)(json, { level: 5 }), gzip: true, turnId } : { data: json, gzip: false, turnId };
|
|
10120
|
+
return chatBody;
|
|
10121
|
+
};
|
|
10097
10122
|
const buildFetchArgs = () => {
|
|
10098
10123
|
const signal = controller.signal;
|
|
10099
10124
|
if (resuming) {
|
|
@@ -10108,12 +10133,15 @@ var require_client = __commonJS({
|
|
|
10108
10133
|
}
|
|
10109
10134
|
return [
|
|
10110
10135
|
`${exports2.API_BASE}/api/code/chat`,
|
|
10111
|
-
{
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10136
|
+
(() => {
|
|
10137
|
+
const body = getChatBody();
|
|
10138
|
+
return {
|
|
10139
|
+
method: "POST",
|
|
10140
|
+
headers: body.gzip ? { ...authHeaders(), "Content-Encoding": "gzip" } : authHeaders(),
|
|
10141
|
+
body: body.data,
|
|
10142
|
+
signal
|
|
10143
|
+
};
|
|
10144
|
+
})()
|
|
10117
10145
|
];
|
|
10118
10146
|
};
|
|
10119
10147
|
const isRetryableStreamMsg = (m2) => {
|
|
@@ -10487,6 +10515,16 @@ var require_client = __commonJS({
|
|
|
10487
10515
|
cache_read_input_tokens: typeof evt.cache_read_input_tokens === "number" ? evt.cache_read_input_tokens : void 0
|
|
10488
10516
|
}
|
|
10489
10517
|
});
|
|
10518
|
+
if (evt.partial !== true && completedMessage?.stopReason === "tool_use" && earlyToolResolveEnabled()) {
|
|
10519
|
+
clearInterval(heartbeatWatchdog);
|
|
10520
|
+
const drainGuard = setTimeout(() => {
|
|
10521
|
+
stream.destroy?.();
|
|
10522
|
+
}, HEARTBEAT_TIMEOUT_MS);
|
|
10523
|
+
drainGuard.unref?.();
|
|
10524
|
+
stream.once("end", () => clearTimeout(drainGuard));
|
|
10525
|
+
stream.once("close", () => clearTimeout(drainGuard));
|
|
10526
|
+
resolve4();
|
|
10527
|
+
}
|
|
10490
10528
|
}
|
|
10491
10529
|
break;
|
|
10492
10530
|
}
|
|
@@ -10524,6 +10562,19 @@ var require_client = __commonJS({
|
|
|
10524
10562
|
serverResumable = true;
|
|
10525
10563
|
break;
|
|
10526
10564
|
}
|
|
10565
|
+
case "tool_use_ready": {
|
|
10566
|
+
if (typeof evt.id === "string" && typeof evt.name === "string") {
|
|
10567
|
+
const input = evt.input && typeof evt.input === "object" ? evt.input : {};
|
|
10568
|
+
onEvent({ type: "tool_use_ready", id: evt.id, name: evt.name, input });
|
|
10569
|
+
}
|
|
10570
|
+
break;
|
|
10571
|
+
}
|
|
10572
|
+
case "runtime_context": {
|
|
10573
|
+
if (typeof evt.text === "string" && evt.text) {
|
|
10574
|
+
onEvent({ type: "runtime_context", text: evt.text });
|
|
10575
|
+
}
|
|
10576
|
+
break;
|
|
10577
|
+
}
|
|
10527
10578
|
case "balance_status": {
|
|
10528
10579
|
const balance = typeof evt.balance === "number" ? evt.balance : 0;
|
|
10529
10580
|
const zero = !!evt.zero;
|
|
@@ -10788,7 +10839,7 @@ var require_client = __commonJS({
|
|
|
10788
10839
|
const data = await response.json();
|
|
10789
10840
|
return {
|
|
10790
10841
|
models: Array.isArray(data.models) ? data.models : [],
|
|
10791
|
-
defaultModel: typeof data.defaultModel === "string" ? data.defaultModel : "
|
|
10842
|
+
defaultModel: typeof data.defaultModel === "string" ? data.defaultModel : "deepseek-flash"
|
|
10792
10843
|
};
|
|
10793
10844
|
}
|
|
10794
10845
|
async function getUsageDaily(days = 30) {
|
|
@@ -12110,7 +12161,7 @@ var require_agentTypes = __commonJS({
|
|
|
12110
12161
|
// edit Z directly" does better work, and withholding it meant every sub-agent
|
|
12111
12162
|
// rediscovered project conventions from scratch. Writing is a different thing
|
|
12112
12163
|
// entirely — memory is durable, cross-session, SHARED state, while sub-agents run
|
|
12113
|
-
// up to
|
|
12164
|
+
// up to 10-wide (configurable) in parallel with their reasoning hidden from the user. A wrong fact
|
|
12114
12165
|
// written there is invisible and permanent, and it competes for a capped, shared
|
|
12115
12166
|
// budget that gets periodically condensed.
|
|
12116
12167
|
//
|
|
@@ -13958,41 +14009,100 @@ var require_tsLangService = __commonJS({
|
|
|
13958
14009
|
return null;
|
|
13959
14010
|
}
|
|
13960
14011
|
var _services = /* @__PURE__ */ new Map();
|
|
13961
|
-
function
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
14012
|
+
function findGoverningConfig(ts, workDir, filePath) {
|
|
14013
|
+
try {
|
|
14014
|
+
if (filePath) {
|
|
14015
|
+
const near = ts.findConfigFile(path8.dirname(filePath), ts.sys.fileExists, "tsconfig.json");
|
|
14016
|
+
if (near)
|
|
14017
|
+
return near;
|
|
14018
|
+
}
|
|
14019
|
+
return ts.findConfigFile(workDir, ts.sys.fileExists, "tsconfig.json") || void 0;
|
|
14020
|
+
} catch {
|
|
14021
|
+
return void 0;
|
|
14022
|
+
}
|
|
14023
|
+
}
|
|
14024
|
+
var MAX_ROOT_FILES = 2e4;
|
|
14025
|
+
var ROOT_RESCAN_MS = Number(process.env.NEXRALL_TS_ROOT_RESCAN_MS ?? 2e3);
|
|
14026
|
+
function getService(workDir, filePath) {
|
|
13965
14027
|
const ts = loadTs(workDir);
|
|
13966
14028
|
if (!ts)
|
|
13967
14029
|
return null;
|
|
14030
|
+
const cfgPath = findGoverningConfig(ts, workDir, filePath);
|
|
14031
|
+
const key = cfgPath ?? workDir;
|
|
14032
|
+
const cached = _services.get(key);
|
|
14033
|
+
if (cached)
|
|
14034
|
+
return cached;
|
|
13968
14035
|
const versions = /* @__PURE__ */ new Map();
|
|
13969
14036
|
const snapshots = /* @__PURE__ */ new Map();
|
|
14037
|
+
const mtimes = /* @__PURE__ */ new Map();
|
|
14038
|
+
const mtimeOf = (fileName) => {
|
|
14039
|
+
try {
|
|
14040
|
+
return fs9.statSync(fileName).mtimeMs;
|
|
14041
|
+
} catch {
|
|
14042
|
+
return -1;
|
|
14043
|
+
}
|
|
14044
|
+
};
|
|
13970
14045
|
const readSource = (fileName) => {
|
|
13971
14046
|
const cachedSrc = snapshots.get(fileName);
|
|
13972
|
-
|
|
14047
|
+
const m2 = mtimeOf(fileName);
|
|
14048
|
+
if (cachedSrc !== void 0 && mtimes.get(fileName) === m2)
|
|
13973
14049
|
return cachedSrc;
|
|
13974
14050
|
try {
|
|
13975
14051
|
const src = fs9.readFileSync(fileName, "utf-8");
|
|
13976
14052
|
snapshots.set(fileName, src);
|
|
14053
|
+
mtimes.set(fileName, m2);
|
|
13977
14054
|
return src;
|
|
13978
14055
|
} catch {
|
|
13979
|
-
return
|
|
14056
|
+
return cachedSrc;
|
|
13980
14057
|
}
|
|
13981
14058
|
};
|
|
13982
14059
|
let options = { allowJs: true, checkJs: false, target: 99, module: 99 };
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
const parsed = ts.readConfigFile(
|
|
13987
|
-
const conf = ts.parseJsonConfigFileContent(parsed.config ?? {}, ts.sys, path8.dirname(
|
|
13988
|
-
if (conf.options)
|
|
14060
|
+
let rootFiles = /* @__PURE__ */ new Set();
|
|
14061
|
+
const addConfig = (cfg, depth) => {
|
|
14062
|
+
try {
|
|
14063
|
+
const parsed = ts.readConfigFile(cfg, ts.sys.readFile);
|
|
14064
|
+
const conf = ts.parseJsonConfigFileContent(parsed.config ?? {}, ts.sys, path8.dirname(cfg));
|
|
14065
|
+
if (depth === 0 && conf.options)
|
|
13989
14066
|
options = { ...conf.options, allowJs: true };
|
|
14067
|
+
for (const f3 of conf.fileNames ?? []) {
|
|
14068
|
+
if (rootFiles.size >= MAX_ROOT_FILES)
|
|
14069
|
+
break;
|
|
14070
|
+
rootFiles.add(path8.resolve(f3));
|
|
14071
|
+
}
|
|
14072
|
+
if (depth === 0 && rootFiles.size === 0) {
|
|
14073
|
+
for (const ref of conf.projectReferences ?? []) {
|
|
14074
|
+
const refCfg = ts.resolveProjectReferencePath ? ts.resolveProjectReferencePath(ref) : ref.path;
|
|
14075
|
+
if (refCfg && ts.sys.fileExists(refCfg))
|
|
14076
|
+
addConfig(refCfg, depth + 1);
|
|
14077
|
+
}
|
|
14078
|
+
}
|
|
14079
|
+
} catch {
|
|
13990
14080
|
}
|
|
13991
|
-
}
|
|
13992
|
-
|
|
14081
|
+
};
|
|
14082
|
+
if (cfgPath)
|
|
14083
|
+
addConfig(cfgPath, 0);
|
|
14084
|
+
let rootsScannedAt = Date.now();
|
|
14085
|
+
const refreshRoots = () => {
|
|
14086
|
+
if (!cfgPath || Date.now() - rootsScannedAt < ROOT_RESCAN_MS)
|
|
14087
|
+
return;
|
|
14088
|
+
rootsScannedAt = Date.now();
|
|
14089
|
+
const prev = rootFiles;
|
|
14090
|
+
rootFiles = /* @__PURE__ */ new Set();
|
|
14091
|
+
addConfig(cfgPath, 0);
|
|
14092
|
+
if (rootFiles.size === 0)
|
|
14093
|
+
rootFiles = prev;
|
|
14094
|
+
};
|
|
13993
14095
|
const host = {
|
|
13994
|
-
getScriptFileNames: () =>
|
|
13995
|
-
|
|
14096
|
+
getScriptFileNames: () => {
|
|
14097
|
+
refreshRoots();
|
|
14098
|
+
if (versions.size === 0)
|
|
14099
|
+
return Array.from(rootFiles);
|
|
14100
|
+
const all = new Set(rootFiles);
|
|
14101
|
+
for (const f3 of versions.keys())
|
|
14102
|
+
all.add(f3);
|
|
14103
|
+
return Array.from(all);
|
|
14104
|
+
},
|
|
14105
|
+
getScriptVersion: (f3) => `${versions.get(f3) ?? 0}:${mtimeOf(f3)}`,
|
|
13996
14106
|
getScriptSnapshot: (f3) => {
|
|
13997
14107
|
const src = readSource(f3);
|
|
13998
14108
|
return src === void 0 ? void 0 : ts.ScriptSnapshot.fromString(src);
|
|
@@ -14008,7 +14118,7 @@ var require_tsLangService = __commonJS({
|
|
|
14008
14118
|
};
|
|
14009
14119
|
const service = ts.createLanguageService(host, ts.createDocumentRegistry());
|
|
14010
14120
|
const svc = { ts, service, root: workDir, versions, snapshots };
|
|
14011
|
-
_services.set(
|
|
14121
|
+
_services.set(key, svc);
|
|
14012
14122
|
return svc;
|
|
14013
14123
|
}
|
|
14014
14124
|
function ensureFile(svc, absPath) {
|
|
@@ -14049,7 +14159,7 @@ var require_tsLangService = __commonJS({
|
|
|
14049
14159
|
return r2.startsWith("..") ? abs : r2;
|
|
14050
14160
|
}
|
|
14051
14161
|
function tsGoToDefinition(deps) {
|
|
14052
|
-
const svc = getService(deps.workDir);
|
|
14162
|
+
const svc = getService(deps.workDir, deps.filePath);
|
|
14053
14163
|
if (!svc)
|
|
14054
14164
|
return null;
|
|
14055
14165
|
if (!ensureFile(svc, deps.filePath))
|
|
@@ -14073,7 +14183,7 @@ var require_tsLangService = __commonJS({
|
|
|
14073
14183
|
${out.join("\n")}` };
|
|
14074
14184
|
}
|
|
14075
14185
|
function tsFindReferences(deps) {
|
|
14076
|
-
const svc = getService(deps.workDir);
|
|
14186
|
+
const svc = getService(deps.workDir, deps.filePath);
|
|
14077
14187
|
if (!svc)
|
|
14078
14188
|
return null;
|
|
14079
14189
|
if (!ensureFile(svc, deps.filePath))
|
|
@@ -14101,7 +14211,7 @@ ${out.join("\n")}` };
|
|
|
14101
14211
|
${lines.join("\n")}` };
|
|
14102
14212
|
}
|
|
14103
14213
|
function tsGetHover(deps) {
|
|
14104
|
-
const svc = getService(deps.workDir);
|
|
14214
|
+
const svc = getService(deps.workDir, deps.filePath);
|
|
14105
14215
|
if (!svc)
|
|
14106
14216
|
return null;
|
|
14107
14217
|
if (!ensureFile(svc, deps.filePath))
|
|
@@ -101374,6 +101484,8 @@ var require_executor = __commonJS({
|
|
|
101374
101484
|
};
|
|
101375
101485
|
}();
|
|
101376
101486
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
101487
|
+
exports2.capExternalOutput = capExternalOutput;
|
|
101488
|
+
exports2.runCapture = runCapture;
|
|
101377
101489
|
exports2.globToRegex = globToRegex;
|
|
101378
101490
|
exports2.executeTool = executeTool;
|
|
101379
101491
|
var fs9 = __importStar(__require("fs"));
|
|
@@ -101668,7 +101780,7 @@ Resolve the conflict (remove <<<<<<< / ======= / >>>>>>> markers and keep the in
|
|
|
101668
101780
|
if (isNew) {
|
|
101669
101781
|
return { output: `Created ${resolved} (${lines} lines, ${bytes} bytes)${sec}`, linesAdded: lines, linesRemoved: 0 };
|
|
101670
101782
|
}
|
|
101671
|
-
const xfile = crossFileBreakageWarning(resolved, normalizeLF(priorContent), normalizeLF(content), workDir ?? process.cwd());
|
|
101783
|
+
const xfile = await crossFileBreakageWarning(resolved, normalizeLF(priorContent), normalizeLF(content), workDir ?? process.cwd());
|
|
101672
101784
|
let tiMarker = "";
|
|
101673
101785
|
const ti = (0, testIntegrity_1.analyzeTestEdit)(resolved, normalizeLF(priorContent), normalizeLF(content));
|
|
101674
101786
|
if (ti.suspicious)
|
|
@@ -102196,17 +102308,104 @@ ${body}` : void 0 }));
|
|
|
102196
102308
|
child.on("close", () => clearInterval(pollAbort));
|
|
102197
102309
|
});
|
|
102198
102310
|
}
|
|
102311
|
+
function capExternalOutput(output, label, maxChars = MAX_OUTPUT_CHARS) {
|
|
102312
|
+
if (output.length <= maxChars)
|
|
102313
|
+
return output;
|
|
102314
|
+
let spillNote = "";
|
|
102315
|
+
try {
|
|
102316
|
+
fs9.mkdirSync(SPILL_DIR, { recursive: true });
|
|
102317
|
+
const safe = label.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 60);
|
|
102318
|
+
const spillPath = path8.join(SPILL_DIR, `${safe}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.log`);
|
|
102319
|
+
fs9.writeFileSync(spillPath, (0, safeSlice_1.sliceSafeEnd)(output, MAX_SPILL_BYTES));
|
|
102320
|
+
spillNote = ` Full output (${output.length} chars) saved to ${spillPath} \u2014 use read_file with offset/limit to inspect any section.`;
|
|
102321
|
+
} catch {
|
|
102322
|
+
}
|
|
102323
|
+
const headLen = Math.floor(maxChars * 0.7);
|
|
102324
|
+
const tailLen = maxChars - headLen;
|
|
102325
|
+
const omitted = output.length - headLen - tailLen;
|
|
102326
|
+
return `${(0, safeSlice_1.sliceSafeEnd)(output, headLen)}
|
|
102327
|
+
|
|
102328
|
+
[\u2026 ${omitted} chars omitted.${spillNote}]
|
|
102329
|
+
|
|
102330
|
+
${(0, safeSlice_1.sliceSafeStart)(output, output.length - tailLen)}`;
|
|
102331
|
+
}
|
|
102332
|
+
function runCapture(cmd, args, opts) {
|
|
102333
|
+
return new Promise((resolve4) => {
|
|
102334
|
+
let stdout = "";
|
|
102335
|
+
let stderr = "";
|
|
102336
|
+
let bytes = 0;
|
|
102337
|
+
let error;
|
|
102338
|
+
let settled = false;
|
|
102339
|
+
let child;
|
|
102340
|
+
try {
|
|
102341
|
+
child = (0, child_process_1.spawn)(cmd, args, { cwd: opts.cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
102342
|
+
} catch (e2) {
|
|
102343
|
+
resolve4({ stdout: "", stderr: "", status: null, signal: null, error: e2 });
|
|
102344
|
+
return;
|
|
102345
|
+
}
|
|
102346
|
+
const finish = (status, signal) => {
|
|
102347
|
+
if (settled)
|
|
102348
|
+
return;
|
|
102349
|
+
settled = true;
|
|
102350
|
+
clearTimeout(timer);
|
|
102351
|
+
resolve4({ stdout, stderr, status, signal, ...error ? { error } : {} });
|
|
102352
|
+
};
|
|
102353
|
+
const kill = (code) => {
|
|
102354
|
+
if (!error)
|
|
102355
|
+
error = Object.assign(new Error(`${cmd} ${code}`), { code });
|
|
102356
|
+
try {
|
|
102357
|
+
child.kill("SIGTERM");
|
|
102358
|
+
} catch {
|
|
102359
|
+
}
|
|
102360
|
+
};
|
|
102361
|
+
const timer = setTimeout(() => kill("ETIMEDOUT"), opts.timeout);
|
|
102362
|
+
child.stdout.setEncoding("utf-8");
|
|
102363
|
+
child.stderr.setEncoding("utf-8");
|
|
102364
|
+
child.stdout.on("data", (chunk) => {
|
|
102365
|
+
if (error)
|
|
102366
|
+
return;
|
|
102367
|
+
bytes += Buffer.byteLength(chunk);
|
|
102368
|
+
if (bytes > opts.maxBuffer) {
|
|
102369
|
+
stdout += chunk.slice(0, Math.max(0, chunk.length - (bytes - opts.maxBuffer)));
|
|
102370
|
+
kill("ENOBUFS");
|
|
102371
|
+
return;
|
|
102372
|
+
}
|
|
102373
|
+
stdout += chunk;
|
|
102374
|
+
});
|
|
102375
|
+
child.stderr.on("data", (chunk) => {
|
|
102376
|
+
if (stderr.length < 64 * 1024)
|
|
102377
|
+
stderr += chunk;
|
|
102378
|
+
});
|
|
102379
|
+
child.on("error", (e2) => {
|
|
102380
|
+
if (!error)
|
|
102381
|
+
error = e2;
|
|
102382
|
+
finish(null, null);
|
|
102383
|
+
});
|
|
102384
|
+
child.on("close", (code, signal) => finish(code, signal));
|
|
102385
|
+
});
|
|
102386
|
+
}
|
|
102199
102387
|
var _rgChecked = false;
|
|
102200
102388
|
var _rgAvailable = false;
|
|
102389
|
+
var _rgBin = "rg";
|
|
102201
102390
|
function ripgrepAvailable() {
|
|
102202
102391
|
if (!_rgChecked) {
|
|
102203
|
-
const probe = (0, child_process_1.spawnSync)("rg", ["--version"], { encoding: "utf-8", timeout: 3e3 });
|
|
102204
|
-
_rgAvailable = probe.status === 0;
|
|
102205
102392
|
_rgChecked = true;
|
|
102393
|
+
const candidates = [process.env.NEXRALL_RG_PATH, "rg"].filter((c) => !!c);
|
|
102394
|
+
for (const bin of candidates) {
|
|
102395
|
+
const probe = (0, child_process_1.spawnSync)(bin, ["--version"], { encoding: "utf-8", timeout: 3e3 });
|
|
102396
|
+
if (probe.status === 0) {
|
|
102397
|
+
_rgBin = bin;
|
|
102398
|
+
_rgAvailable = true;
|
|
102399
|
+
break;
|
|
102400
|
+
}
|
|
102401
|
+
}
|
|
102206
102402
|
}
|
|
102207
102403
|
return _rgAvailable;
|
|
102208
102404
|
}
|
|
102209
|
-
function
|
|
102405
|
+
function rgBin() {
|
|
102406
|
+
return _rgBin;
|
|
102407
|
+
}
|
|
102408
|
+
async function crossFileBreakageWarning(editedAbsPath, oldContent, newContent, workDir) {
|
|
102210
102409
|
if (process.env.NEXRALL_CROSSFILE_CHECK === "0")
|
|
102211
102410
|
return "";
|
|
102212
102411
|
let removed;
|
|
@@ -102226,8 +102425,8 @@ ${body}` : void 0 }));
|
|
|
102226
102425
|
})();
|
|
102227
102426
|
const hits = [];
|
|
102228
102427
|
const MAX_SYMBOLS = 8;
|
|
102229
|
-
|
|
102230
|
-
|
|
102428
|
+
const scanned = await Promise.all(removed.slice(0, MAX_SYMBOLS).map(async (sym) => ({ sym, refs: await scanReferences(sym.name, workDir, editedReal) })));
|
|
102429
|
+
for (const { sym, refs } of scanned) {
|
|
102231
102430
|
if (refs.length) {
|
|
102232
102431
|
const shown = refs.slice(0, 3).map((r2) => ` ${r2}`).join("\n");
|
|
102233
102432
|
const more = refs.length > 3 ? `
|
|
@@ -102244,44 +102443,26 @@ ${shown}${more}`);
|
|
|
102244
102443
|
` + hits.join("\n") + `
|
|
102245
102444
|
Update these call-sites (or restore the symbol), then run a build/typecheck to confirm nothing is broken.`;
|
|
102246
102445
|
}
|
|
102247
|
-
function scanReferences(name, workDir, excludeRealPath) {
|
|
102446
|
+
async function scanReferences(name, workDir, excludeRealPath) {
|
|
102248
102447
|
const pattern = `\\b${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`;
|
|
102249
102448
|
const files = /* @__PURE__ */ new Set();
|
|
102250
102449
|
try {
|
|
102251
|
-
|
|
102252
|
-
|
|
102253
|
-
|
|
102254
|
-
|
|
102255
|
-
|
|
102256
|
-
|
|
102257
|
-
|
|
102258
|
-
|
|
102259
|
-
|
|
102260
|
-
|
|
102261
|
-
|
|
102262
|
-
|
|
102263
|
-
|
|
102264
|
-
|
|
102265
|
-
|
|
102266
|
-
|
|
102267
|
-
"--exclude-dir=.git",
|
|
102268
|
-
"--exclude-dir=dist",
|
|
102269
|
-
"--exclude-dir=.next",
|
|
102270
|
-
"-E",
|
|
102271
|
-
pattern,
|
|
102272
|
-
"."
|
|
102273
|
-
], {
|
|
102274
|
-
cwd: workDir,
|
|
102275
|
-
encoding: "utf-8",
|
|
102276
|
-
timeout: 8e3,
|
|
102277
|
-
maxBuffer: 8 * 1024 * 1024
|
|
102278
|
-
});
|
|
102279
|
-
if (r2.stdout)
|
|
102280
|
-
for (const line of r2.stdout.split("\n")) {
|
|
102281
|
-
if (line.trim())
|
|
102282
|
-
files.add(line.trim());
|
|
102283
|
-
}
|
|
102284
|
-
}
|
|
102450
|
+
const opts = { cwd: workDir, timeout: 8e3, maxBuffer: 8 * 1024 * 1024 };
|
|
102451
|
+
const r2 = ripgrepAvailable() ? await runCapture(rgBin(), ["-l", "--no-messages", "-e", pattern, "."], opts) : await runCapture("grep", [
|
|
102452
|
+
"-rlI",
|
|
102453
|
+
"--exclude-dir=node_modules",
|
|
102454
|
+
"--exclude-dir=.git",
|
|
102455
|
+
"--exclude-dir=dist",
|
|
102456
|
+
"--exclude-dir=.next",
|
|
102457
|
+
"-E",
|
|
102458
|
+
pattern,
|
|
102459
|
+
"."
|
|
102460
|
+
], opts);
|
|
102461
|
+
if (r2.stdout)
|
|
102462
|
+
for (const line of r2.stdout.split("\n")) {
|
|
102463
|
+
if (line.trim())
|
|
102464
|
+
files.add(line.trim());
|
|
102465
|
+
}
|
|
102285
102466
|
} catch {
|
|
102286
102467
|
return [];
|
|
102287
102468
|
}
|
|
@@ -102314,7 +102495,8 @@ Update these call-sites (or restore the symbol), then run a build/typecheck to c
|
|
|
102314
102495
|
if (searchType === "filename") {
|
|
102315
102496
|
const matches = [];
|
|
102316
102497
|
const patternLower = pattern.toLowerCase();
|
|
102317
|
-
|
|
102498
|
+
const listing = await listFiles(resolved);
|
|
102499
|
+
listing.files.forEach((filePath) => {
|
|
102318
102500
|
const name = path8.basename(filePath);
|
|
102319
102501
|
const nameLower = name.toLowerCase();
|
|
102320
102502
|
const rel = path8.relative(resolved, filePath).replace(/\\/g, "/");
|
|
@@ -102332,6 +102514,9 @@ Update these call-sites (or restore the symbol), then run a build/typecheck to c
|
|
|
102332
102514
|
}).join("\n");
|
|
102333
102515
|
if (out.length > MAX_OUTPUT_CHARS)
|
|
102334
102516
|
out = (0, safeSlice_1.sliceSafeEnd)(out, MAX_OUTPUT_CHARS) + "\n[Truncated]";
|
|
102517
|
+
if (listing.truncated)
|
|
102518
|
+
out += `
|
|
102519
|
+
[Scan stopped after ${WALK_MAX_FILES.toLocaleString("en-US")} files \u2014 narrow the path for complete results.]`;
|
|
102335
102520
|
return { output: out };
|
|
102336
102521
|
} else {
|
|
102337
102522
|
const SEARCH_MAX_BUFFER = 64 * 1024 * 1024;
|
|
@@ -102339,7 +102524,7 @@ Update these call-sites (or restore the symbol), then run a build/typecheck to c
|
|
|
102339
102524
|
const relTarget = path8.relative(base, resolved);
|
|
102340
102525
|
const inside = !relTarget.startsWith("..") && !path8.isAbsolute(relTarget);
|
|
102341
102526
|
const target = inside ? relTarget || "." : resolved;
|
|
102342
|
-
const spawnOpts = {
|
|
102527
|
+
const spawnOpts = { timeout: DEFAULT_TIMEOUT_MS, maxBuffer: SEARCH_MAX_BUFFER, cwd: base };
|
|
102343
102528
|
let result;
|
|
102344
102529
|
if (ripgrepAvailable()) {
|
|
102345
102530
|
const args = filesOnly ? ["--files-with-matches", "--color=never", "--hidden", "--glob", "!.git"] : [
|
|
@@ -102361,7 +102546,7 @@ Update these call-sites (or restore the symbol), then run a build/typecheck to c
|
|
|
102361
102546
|
if (include)
|
|
102362
102547
|
args.push("--glob", include);
|
|
102363
102548
|
args.push("-m", "200", "--regexp", pattern, target);
|
|
102364
|
-
result = (
|
|
102549
|
+
result = await runCapture(rgBin(), args, spawnOpts);
|
|
102365
102550
|
} else {
|
|
102366
102551
|
const args = [filesOnly ? "-rlE" : "-rnE", "--binary-files=without-match", "--color=never"];
|
|
102367
102552
|
if (ignoreCase)
|
|
@@ -102371,13 +102556,13 @@ Update these call-sites (or restore the symbol), then run a build/typecheck to c
|
|
|
102371
102556
|
if (include)
|
|
102372
102557
|
args.push(`--include=${include}`);
|
|
102373
102558
|
args.push("--exclude-dir=.git", "--exclude-dir=node_modules", "--exclude-dir=dist", "--exclude-dir=.next", "--exclude-dir=__pycache__", "--exclude-dir=.turbo", "--exclude-dir=coverage", "--exclude-dir=.cache", "--exclude-dir=.venv", "--exclude-dir=venv", "-m", "200", pattern, target);
|
|
102374
|
-
result =
|
|
102559
|
+
result = await runCapture("grep", args, spawnOpts);
|
|
102375
102560
|
}
|
|
102376
102561
|
let output = (result.stdout ?? "").replace(/^\.\//gm, "");
|
|
102377
102562
|
const stderr = result.stderr ?? "";
|
|
102378
102563
|
const spawnErr = result.error;
|
|
102379
102564
|
if (spawnErr) {
|
|
102380
|
-
if (spawnErr.code === "ETIMEDOUT" || result.signal === "SIGTERM") {
|
|
102565
|
+
if (spawnErr.code === "ETIMEDOUT" || result.signal === "SIGTERM" && spawnErr.code !== "ENOBUFS") {
|
|
102381
102566
|
const partial = output ? `
|
|
102382
102567
|
|
|
102383
102568
|
Partial results before timeout:
|
|
@@ -102393,7 +102578,7 @@ ${globalCapMatches(output)}` : "";
|
|
|
102393
102578
|
if (result.status === 1 && !output)
|
|
102394
102579
|
return { output: "No matches found." };
|
|
102395
102580
|
if (result.status !== 0 && result.status !== 1) {
|
|
102396
|
-
const hint = /parenthes|bracket|brace|Unmatched|repetition-operator|invalid regex/i.test(stderr) ? ' \u2014 the pattern has invalid/unbalanced regex syntax. If you meant to match literal parentheses/brackets, escape them (e.g. "\\(", "\\)"), or simplify the pattern.' : "";
|
|
102581
|
+
const hint = /parenthes|bracket|brace|Unmatched|unclosed|repetition-operator|invalid regex/i.test(stderr) ? ' \u2014 the pattern has invalid/unbalanced regex syntax. If you meant to match literal parentheses/brackets, escape them (e.g. "\\(", "\\)"), or simplify the pattern.' : "";
|
|
102397
102582
|
return { error: (stderr || "search failed").trim() + hint };
|
|
102398
102583
|
}
|
|
102399
102584
|
if (filesOnly) {
|
|
@@ -102475,11 +102660,36 @@ ${globalCapMatches(output)}` : "";
|
|
|
102475
102660
|
".idea",
|
|
102476
102661
|
".DS_Store"
|
|
102477
102662
|
]);
|
|
102663
|
+
var WALK_MAX_FILES = 5e4;
|
|
102664
|
+
async function listFiles(root) {
|
|
102665
|
+
if (ripgrepAvailable()) {
|
|
102666
|
+
const args = ["--files", "--hidden", "--follow", "--no-messages", "--color=never"];
|
|
102667
|
+
for (const d of WALK_SKIP_DIRS)
|
|
102668
|
+
args.push("--glob", `!**/${d}/**`);
|
|
102669
|
+
args.push(".");
|
|
102670
|
+
const r2 = await runCapture(rgBin(), args, { cwd: root, timeout: DEFAULT_TIMEOUT_MS, maxBuffer: 64 * 1024 * 1024 });
|
|
102671
|
+
if (!r2.error && (r2.status === 0 || r2.status === 1 || r2.status === 2 && r2.stdout)) {
|
|
102672
|
+
const files2 = r2.stdout.split("\n").filter(Boolean).map((f3) => path8.join(root, f3.replace(/^\.\//, "")));
|
|
102673
|
+
return { files: files2, truncated: false };
|
|
102674
|
+
}
|
|
102675
|
+
}
|
|
102676
|
+
const files = [];
|
|
102677
|
+
let truncated = false;
|
|
102678
|
+
walkDir(root, (f3) => {
|
|
102679
|
+
if (files.length >= WALK_MAX_FILES) {
|
|
102680
|
+
truncated = true;
|
|
102681
|
+
return false;
|
|
102682
|
+
}
|
|
102683
|
+
files.push(f3);
|
|
102684
|
+
return true;
|
|
102685
|
+
});
|
|
102686
|
+
return { files, truncated };
|
|
102687
|
+
}
|
|
102478
102688
|
function walkDir(dirPath, callback, _visited = /* @__PURE__ */ new Set()) {
|
|
102479
102689
|
try {
|
|
102480
102690
|
const real = fs9.realpathSync(dirPath);
|
|
102481
102691
|
if (_visited.has(real))
|
|
102482
|
-
return;
|
|
102692
|
+
return true;
|
|
102483
102693
|
_visited.add(real);
|
|
102484
102694
|
const entries = fs9.readdirSync(dirPath, { withFileTypes: true });
|
|
102485
102695
|
for (const entry of entries) {
|
|
@@ -102494,13 +102704,15 @@ ${globalCapMatches(output)}` : "";
|
|
|
102494
102704
|
if (isDir) {
|
|
102495
102705
|
if (WALK_SKIP_DIRS.has(entry.name))
|
|
102496
102706
|
continue;
|
|
102497
|
-
walkDir(fullPath, callback, _visited)
|
|
102498
|
-
|
|
102499
|
-
|
|
102707
|
+
if (walkDir(fullPath, callback, _visited) === false)
|
|
102708
|
+
return false;
|
|
102709
|
+
} else if (callback(fullPath) === false) {
|
|
102710
|
+
return false;
|
|
102500
102711
|
}
|
|
102501
102712
|
}
|
|
102502
102713
|
} catch {
|
|
102503
102714
|
}
|
|
102715
|
+
return true;
|
|
102504
102716
|
}
|
|
102505
102717
|
async function createDirectory(input, workDir) {
|
|
102506
102718
|
const dirPath = typeof input.path === "string" ? input.path : "";
|
|
@@ -102658,7 +102870,7 @@ ${globalCapMatches(output)}` : "";
|
|
|
102658
102870
|
const diff3 = buildDiff(filePath, oldNorm, newNorm, origNorm);
|
|
102659
102871
|
const linesBefore = origNorm.split("\n").length;
|
|
102660
102872
|
const linesAfter = updated.split("\n").length;
|
|
102661
|
-
const xfile = crossFileBreakageWarning(resolved, origNorm, normalizeLF(updated), workDir ?? process.cwd());
|
|
102873
|
+
const xfile = await crossFileBreakageWarning(resolved, origNorm, normalizeLF(updated), workDir ?? process.cwd());
|
|
102662
102874
|
const sec = (0, securityLint_1.securityNoteText)((0, securityLint_1.checkSecurity)(newNorm));
|
|
102663
102875
|
return {
|
|
102664
102876
|
output: `Edited ${resolved} (${linesBefore} \u2192 ${linesAfter} lines)
|
|
@@ -103034,7 +103246,7 @@ ${body}${truncNote}
|
|
|
103034
103246
|
}
|
|
103035
103247
|
const finalContent = wasCRLF ? content.replace(/\n/g, "\r\n") : content;
|
|
103036
103248
|
atomicWritePreservingMode(resolved, finalContent, pre.mode);
|
|
103037
|
-
const xfile = crossFileBreakageWarning(resolved, originalNorm, content, workDir ?? process.cwd());
|
|
103249
|
+
const xfile = await crossFileBreakageWarning(resolved, originalNorm, content, workDir ?? process.cwd());
|
|
103038
103250
|
const sec = (0, securityLint_1.securityNoteText)((0, securityLint_1.checkSecurity)(insertedText.join("\n")));
|
|
103039
103251
|
return {
|
|
103040
103252
|
output: `Applied ${edits.length} edit(s) to ${resolved}:
|
|
@@ -103058,14 +103270,17 @@ ${d}`).join("\n") + xfile + sec,
|
|
|
103058
103270
|
const matches = [];
|
|
103059
103271
|
const regex2 = globToRegex(pattern);
|
|
103060
103272
|
const useBasename = !pattern.includes("/") && !pattern.includes("**");
|
|
103061
|
-
|
|
103273
|
+
const listing = await listFiles(resolved);
|
|
103274
|
+
for (const filePath of listing.files) {
|
|
103062
103275
|
const rel = path8.relative(resolved, filePath).replace(/\\/g, "/");
|
|
103063
103276
|
if (regex2.test(rel) || useBasename && regex2.test(path8.basename(filePath))) {
|
|
103064
103277
|
matches.push(filePath);
|
|
103065
103278
|
}
|
|
103066
|
-
}
|
|
103279
|
+
}
|
|
103280
|
+
const scanNote = listing.truncated ? `
|
|
103281
|
+
[Scan stopped after ${WALK_MAX_FILES.toLocaleString("en-US")} files \u2014 narrow the path for complete results.]` : "";
|
|
103067
103282
|
if (!matches.length)
|
|
103068
|
-
return { output: `No files matched pattern: ${pattern}` };
|
|
103283
|
+
return { output: `No files matched pattern: ${pattern}${scanNote}` };
|
|
103069
103284
|
const mtime = (f3) => {
|
|
103070
103285
|
try {
|
|
103071
103286
|
return fs9.statSync(f3).mtimeMs;
|
|
@@ -103078,7 +103293,7 @@ ${d}`).join("\n") + xfile + sec,
|
|
|
103078
103293
|
const more = sorted.length > shown.length ? `
|
|
103079
103294
|
[${sorted.length - shown.length} more not shown \u2014 narrow the pattern or path]` : "";
|
|
103080
103295
|
return { output: `${matches.length} file(s) matched "${pattern}" under ${resolved}:
|
|
103081
|
-
${shown.join("\n")}${more}` };
|
|
103296
|
+
${shown.join("\n")}${more}${scanNote}` };
|
|
103082
103297
|
} catch (err) {
|
|
103083
103298
|
return { error: err.message };
|
|
103084
103299
|
}
|
|
@@ -103978,6 +104193,88 @@ var require_readDedupe = __commonJS({
|
|
|
103978
104193
|
}
|
|
103979
104194
|
});
|
|
103980
104195
|
|
|
104196
|
+
// ../core/dist/agent/toolPrefetch.js
|
|
104197
|
+
var require_toolPrefetch = __commonJS({
|
|
104198
|
+
"../core/dist/agent/toolPrefetch.js"(exports2) {
|
|
104199
|
+
"use strict";
|
|
104200
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
104201
|
+
exports2.ToolPrefetcher = exports2.PREFETCHABLE_TOOLS = void 0;
|
|
104202
|
+
exports2.isPrefetchSafeMessage = isPrefetchSafeMessage;
|
|
104203
|
+
exports2.toolPrefetchEnabled = toolPrefetchEnabled;
|
|
104204
|
+
exports2.PREFETCHABLE_TOOLS = /* @__PURE__ */ new Set([
|
|
104205
|
+
"read_file",
|
|
104206
|
+
"list_directory",
|
|
104207
|
+
"glob",
|
|
104208
|
+
"search_files"
|
|
104209
|
+
]);
|
|
104210
|
+
var NON_MUTATING_COMPANIONS = /* @__PURE__ */ new Set([
|
|
104211
|
+
...exports2.PREFETCHABLE_TOOLS,
|
|
104212
|
+
"notebook_read",
|
|
104213
|
+
"todo_write",
|
|
104214
|
+
"todo_read",
|
|
104215
|
+
"memory_read",
|
|
104216
|
+
"use_skill",
|
|
104217
|
+
"fetch_url",
|
|
104218
|
+
"web_search",
|
|
104219
|
+
"get_diagnostics",
|
|
104220
|
+
"go_to_definition",
|
|
104221
|
+
"find_references",
|
|
104222
|
+
"get_symbols",
|
|
104223
|
+
"get_workspace_symbols",
|
|
104224
|
+
"get_hover"
|
|
104225
|
+
]);
|
|
104226
|
+
function isPrefetchSafeMessage(toolNames) {
|
|
104227
|
+
return toolNames.every((n) => NON_MUTATING_COMPANIONS.has(n));
|
|
104228
|
+
}
|
|
104229
|
+
function toolPrefetchEnabled() {
|
|
104230
|
+
return process.env.NEXRALL_TOOL_PREFETCH !== "0";
|
|
104231
|
+
}
|
|
104232
|
+
function stableKey(value) {
|
|
104233
|
+
if (value === null || typeof value !== "object")
|
|
104234
|
+
return JSON.stringify(value) ?? "undefined";
|
|
104235
|
+
if (Array.isArray(value))
|
|
104236
|
+
return `[${value.map(stableKey).join(",")}]`;
|
|
104237
|
+
const obj2 = value;
|
|
104238
|
+
return `{${Object.keys(obj2).sort().map((k) => `${JSON.stringify(k)}:${stableKey(obj2[k])}`).join(",")}}`;
|
|
104239
|
+
}
|
|
104240
|
+
var ToolPrefetcher = class {
|
|
104241
|
+
constructor(run) {
|
|
104242
|
+
this.run = run;
|
|
104243
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
104244
|
+
}
|
|
104245
|
+
/** Start `name` early if it is a pure read. Idempotent per id. */
|
|
104246
|
+
start(id, name, input) {
|
|
104247
|
+
if (!id || !exports2.PREFETCHABLE_TOOLS.has(name) || this.entries.has(id))
|
|
104248
|
+
return false;
|
|
104249
|
+
const promise = Promise.resolve().then(() => this.run(name, input)).catch((err) => ({ error: `Tool execution failed: ${err?.message ?? String(err)}` }));
|
|
104250
|
+
this.entries.set(id, { name, key: stableKey(input), promise });
|
|
104251
|
+
return true;
|
|
104252
|
+
}
|
|
104253
|
+
/**
|
|
104254
|
+
* The prefetched result for exactly this call, or null. Always removes the entry,
|
|
104255
|
+
* so a result is handed out at most once.
|
|
104256
|
+
*/
|
|
104257
|
+
take(id, name, input) {
|
|
104258
|
+
const e2 = this.entries.get(id);
|
|
104259
|
+
if (!e2)
|
|
104260
|
+
return null;
|
|
104261
|
+
this.entries.delete(id);
|
|
104262
|
+
if (e2.name !== name || e2.key !== stableKey(input))
|
|
104263
|
+
return null;
|
|
104264
|
+
return e2.promise;
|
|
104265
|
+
}
|
|
104266
|
+
/** Drop everything (stream restarted — the ids it announced will never be dispatched). */
|
|
104267
|
+
clear() {
|
|
104268
|
+
this.entries.clear();
|
|
104269
|
+
}
|
|
104270
|
+
get size() {
|
|
104271
|
+
return this.entries.size;
|
|
104272
|
+
}
|
|
104273
|
+
};
|
|
104274
|
+
exports2.ToolPrefetcher = ToolPrefetcher;
|
|
104275
|
+
}
|
|
104276
|
+
});
|
|
104277
|
+
|
|
103981
104278
|
// ../core/dist/agent/worktree.js
|
|
103982
104279
|
var require_worktree = __commonJS({
|
|
103983
104280
|
"../core/dist/agent/worktree.js"(exports2) {
|
|
@@ -106118,9 +106415,11 @@ var require_loop = __commonJS({
|
|
|
106118
106415
|
exports2.contextWindowFor = contextWindowFor2;
|
|
106119
106416
|
exports2.compactionLimits = compactionLimits;
|
|
106120
106417
|
exports2.compactionThresholds = compactionThresholds2;
|
|
106418
|
+
exports2.pruneReclaimFloor = pruneReclaimFloor;
|
|
106121
106419
|
exports2.estimateBodyBytes = estimateBodyBytes2;
|
|
106122
106420
|
exports2.allowsTestOnlyWrite = allowsTestOnlyWrite;
|
|
106123
106421
|
exports2.findSafeCutIndex = findSafeCutIndex;
|
|
106422
|
+
exports2.persistRuntimeContext = persistRuntimeContext;
|
|
106124
106423
|
exports2.transcriptOf = transcriptOf;
|
|
106125
106424
|
exports2.createLedger = createLedger;
|
|
106126
106425
|
exports2.ledgerRecord = ledgerRecord;
|
|
@@ -106134,6 +106433,7 @@ var require_loop = __commonJS({
|
|
|
106134
106433
|
exports2.runAgentLoop = runAgentLoop2;
|
|
106135
106434
|
exports2.trimToResumableBoundary = trimToResumableBoundary;
|
|
106136
106435
|
var readDedupe_1 = require_readDedupe();
|
|
106436
|
+
var toolPrefetch_1 = require_toolPrefetch();
|
|
106137
106437
|
var worktree_1 = require_worktree();
|
|
106138
106438
|
var backgroundAgents_1 = require_backgroundAgents();
|
|
106139
106439
|
var types_1 = require_types();
|
|
@@ -106475,9 +106775,10 @@ ${ctx.repeatError}
|
|
|
106475
106775
|
const abs = raw.map((p) => workDir ? path8.resolve(workDir, p) : p);
|
|
106476
106776
|
return abs.length ? abs : [name];
|
|
106477
106777
|
}
|
|
106478
|
-
var DEFAULT_MAX_CONCURRENT_SUBTASKS =
|
|
106778
|
+
var DEFAULT_MAX_CONCURRENT_SUBTASKS = 10;
|
|
106779
|
+
var HARD_MAX_CONCURRENT_SUBTASKS = 32;
|
|
106479
106780
|
function resolveMaxConcurrentSubtasks(settingsRaw = {}) {
|
|
106480
|
-
const clamp = (n) => Math.max(1, Math.min(Math.floor(n),
|
|
106781
|
+
const clamp = (n) => Math.max(1, Math.min(Math.floor(n), HARD_MAX_CONCURRENT_SUBTASKS));
|
|
106481
106782
|
const fromEnv = Number(process.env.NEXRALL_MAX_CONCURRENT_SUBTASKS);
|
|
106482
106783
|
if (Number.isFinite(fromEnv) && fromEnv > 0)
|
|
106483
106784
|
return clamp(fromEnv);
|
|
@@ -106954,12 +107255,12 @@ ${sk.body.trim()}` : `# Preloaded skill: ${n}
|
|
|
106954
107255
|
}).join("\n\n");
|
|
106955
107256
|
}
|
|
106956
107257
|
const subNexrallMd = [
|
|
107258
|
+
inheritedMd,
|
|
106957
107259
|
SUBAGENT_PREAMBLE,
|
|
106958
107260
|
agent ? `# Sub-agent role: ${agent.name}
|
|
106959
107261
|
${agent.prompt}` : "",
|
|
106960
107262
|
preloadedSkills,
|
|
106961
|
-
agentMemoryNotes
|
|
106962
|
-
inheritedMd
|
|
107263
|
+
agentMemoryNotes
|
|
106963
107264
|
].filter(Boolean).join("\n\n---\n\n");
|
|
106964
107265
|
const testFilesOnly = !!agent?.testFilesOnly || !!options._testFilesOnly;
|
|
106965
107266
|
const allowed = intersectAllowlists(agent?.tools ? new Set(agent.tools) : null, options._allowedTools);
|
|
@@ -107394,6 +107695,12 @@ ${partial}` : "",
|
|
|
107394
107695
|
return { prune: prune / contextWindow, compact: compact / contextWindow };
|
|
107395
107696
|
}
|
|
107396
107697
|
var PRUNE_MIN_RECLAIM_BYTES = 96 * 1024;
|
|
107698
|
+
var PRUNE_MIN_RECLAIM_BYTES_COLD = 16 * 1024;
|
|
107699
|
+
var CACHE_COLD_AFTER_MS = 5 * 6e4;
|
|
107700
|
+
var _lastApiCallEndedAt = /* @__PURE__ */ new Map();
|
|
107701
|
+
function pruneReclaimFloor(lastCallEndedAt, now = Date.now()) {
|
|
107702
|
+
return lastCallEndedAt !== void 0 && now - lastCallEndedAt >= CACHE_COLD_AFTER_MS ? PRUNE_MIN_RECLAIM_BYTES_COLD : PRUNE_MIN_RECLAIM_BYTES;
|
|
107703
|
+
}
|
|
107397
107704
|
var COMPACT_KEEP_MIN = 6;
|
|
107398
107705
|
var COMPACT_MIN_RECLAIM_BYTES = 32 * 1024;
|
|
107399
107706
|
var COMPACT_MAX_FAILURES = 3;
|
|
@@ -107448,10 +107755,22 @@ ${partial}` : "",
|
|
|
107448
107755
|
return -1;
|
|
107449
107756
|
}
|
|
107450
107757
|
var MAX_TRANSCRIPT_CHARS = 6e5;
|
|
107758
|
+
function persistRuntimeContext(messages, idx, text) {
|
|
107759
|
+
const m2 = messages[idx];
|
|
107760
|
+
if (!m2 || m2.role !== "user" || !Array.isArray(m2.content))
|
|
107761
|
+
return false;
|
|
107762
|
+
const lastBlock = m2.content[m2.content.length - 1];
|
|
107763
|
+
if (lastBlock && lastBlock.type === "text" && lastBlock.text === text)
|
|
107764
|
+
return false;
|
|
107765
|
+
messages[idx] = { ...m2, content: [...m2.content, { type: "text", text }] };
|
|
107766
|
+
return true;
|
|
107767
|
+
}
|
|
107451
107768
|
function transcriptOf(messages) {
|
|
107452
107769
|
const parts = [];
|
|
107453
107770
|
for (const m2 of messages) {
|
|
107454
107771
|
for (const b of m2.content) {
|
|
107772
|
+
if ((0, types_1.isRuntimeContextBlock)(b))
|
|
107773
|
+
continue;
|
|
107455
107774
|
if (b.type === "text" && b.text) {
|
|
107456
107775
|
parts.push(`${m2.role.toUpperCase()}: ${(0, safeSlice_1.sliceSafeEnd)(b.text, 2e3)}`);
|
|
107457
107776
|
} else if (b.type === "tool_use") {
|
|
@@ -107604,7 +107923,7 @@ ${tail}`;
|
|
|
107604
107923
|
const first = messages.find((m2) => m2.role === "user");
|
|
107605
107924
|
if (!first || !Array.isArray(first.content))
|
|
107606
107925
|
return "";
|
|
107607
|
-
return first.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n").trim();
|
|
107926
|
+
return first.content.filter((b) => b.type === "text" && b.text && !(0, types_1.isRuntimeContextBlock)(b)).map((b) => b.text).join("\n").trim();
|
|
107608
107927
|
}
|
|
107609
107928
|
var CompactionUnavailableError = class extends Error {
|
|
107610
107929
|
constructor() {
|
|
@@ -107662,7 +107981,14 @@ Do NOT call any tools and do NOT continue the task. Reply with text only: a conc
|
|
|
107662
107981
|
// surprise charge on a different provider. Falls back to the same
|
|
107663
107982
|
// default as the main loop (see `runAgentLoop`) only when no model was
|
|
107664
107983
|
// set at all.
|
|
107665
|
-
|
|
107984
|
+
//
|
|
107985
|
+
// Cheapest model of the SAME vendor (Claude Code runs this kind of work on
|
|
107986
|
+
// Haiku). Safe to downgrade HERE because this fallback sends a fresh
|
|
107987
|
+
// transcript — it shares no cached prefix with the conversation, unlike
|
|
107988
|
+
// summarizeCached above, which must stay on the conversation's own model.
|
|
107989
|
+
// Never crosses providers; falls back to the session model if the
|
|
107990
|
+
// catalogue is not loaded.
|
|
107991
|
+
model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "turbo") ?? options.model ?? "turbo",
|
|
107666
107992
|
mode: "ask",
|
|
107667
107993
|
// summariser must not call tools; ask-mode discourages action
|
|
107668
107994
|
env: options.env,
|
|
@@ -107705,7 +108031,9 @@ Continue the work from here.` }] });
|
|
|
107705
108031
|
// Same reasoning as autoCompactMessages' summariser: run on the same
|
|
107706
108032
|
// model as the actual conversation rather than forcing a fixed tier
|
|
107707
108033
|
// (which silently billed Anthropic regardless of the user's provider).
|
|
107708
|
-
model:
|
|
108034
|
+
// Cheapest SAME-vendor model: a fresh prompt with no shared cache prefix,
|
|
108035
|
+
// and merging a few memory bullets does not need the session's top tier.
|
|
108036
|
+
model: (0, modelCatalogue_1.cheapestSameVendorModel)(options.model ?? "turbo") ?? options.model ?? "turbo",
|
|
107709
108037
|
mode: "ask",
|
|
107710
108038
|
env: options.env,
|
|
107711
108039
|
clientType: options.clientType,
|
|
@@ -107985,11 +108313,11 @@ Continue the work from here.` }] });
|
|
|
107985
108313
|
const tokenPressure = lastPromptTokens > compactLimits.compact;
|
|
107986
108314
|
let bytePressure = bodyBytes > MAX_BODY_BYTES;
|
|
107987
108315
|
if (autoCompact && !compacting && (prunePressure || bytePressure) && messages.length > PRUNE_KEEP_RECENT + 2) {
|
|
107988
|
-
const
|
|
108316
|
+
const floor = depth === 0 ? pruneReclaimFloor(_lastApiCallEndedAt.get(options.sessionId || PROCESS_BUDGET_KEY)) : PRUNE_MIN_RECLAIM_BYTES;
|
|
108317
|
+
const reclaimed = pruneOldToolResults(messages, floor);
|
|
107989
108318
|
if (reclaimed > 0) {
|
|
107990
108319
|
bodyBytes = estimateBodyBytes2(messages);
|
|
107991
108320
|
bytePressure = bodyBytes > MAX_BODY_BYTES;
|
|
107992
|
-
(options.onNotice ?? options.onText)(`\u267B\uFE0F Trimmed ~${(reclaimed / (1024 * 1024)).toFixed(1)}MB of already-processed tool output to keep this chat cheap to continue.`);
|
|
107993
108321
|
}
|
|
107994
108322
|
}
|
|
107995
108323
|
if (compactDisabled && bodyBytes > compactDisabledAtBytes * COMPACT_REARM_GROWTH) {
|
|
@@ -108014,7 +108342,6 @@ Continue the work from here.` }] });
|
|
|
108014
108342
|
if (did) {
|
|
108015
108343
|
lastPromptTokens = 0;
|
|
108016
108344
|
const reason = bytePressure ? `body ~${(bodyBytes / (1024 * 1024)).toFixed(1)}MB` : "context window";
|
|
108017
|
-
(options.onNotice ?? options.onText)(`\u267B\uFE0F Auto-compacted earlier conversation to stay within the ${reason}.`);
|
|
108018
108345
|
bodyBytes = bytesAfter;
|
|
108019
108346
|
bytePressure = bodyBytes > MAX_BODY_BYTES;
|
|
108020
108347
|
}
|
|
@@ -108035,6 +108362,10 @@ Continue the work from here.` }] });
|
|
|
108035
108362
|
\u26A0\uFE0F Approaching the ${budget}-step limit (step ${iteration + 1}). Please wrap up and summarise what has been done.
|
|
108036
108363
|
`);
|
|
108037
108364
|
}
|
|
108365
|
+
let pendingRuntimeContext = null;
|
|
108366
|
+
const sentUserIdx = messages.length - 1;
|
|
108367
|
+
const prefetcher = new toolPrefetch_1.ToolPrefetcher((toolName, toolInput) => (0, executor_1.executeTool)(toolName, toolInput, options.abortSignal, sandboxCfg, options.workDir, agentScope, void 0, options.selfPeer));
|
|
108368
|
+
const prefetchOn = (0, toolPrefetch_1.toolPrefetchEnabled)();
|
|
108038
108369
|
const onEvent = (event) => {
|
|
108039
108370
|
switch (event.type) {
|
|
108040
108371
|
case "text":
|
|
@@ -108066,11 +108397,19 @@ Continue the work from here.` }] });
|
|
|
108066
108397
|
options.onRetryResolved?.();
|
|
108067
108398
|
break;
|
|
108068
108399
|
case "stream_restart":
|
|
108400
|
+
prefetcher.clear();
|
|
108069
108401
|
options.onStreamRestart?.(event.reason, event.discardedChars);
|
|
108070
108402
|
break;
|
|
108071
108403
|
case "balance_status":
|
|
108072
108404
|
options.onBalanceStatus?.(event.balance, event.zero);
|
|
108073
108405
|
break;
|
|
108406
|
+
case "runtime_context":
|
|
108407
|
+
pendingRuntimeContext = event.text;
|
|
108408
|
+
break;
|
|
108409
|
+
case "tool_use_ready":
|
|
108410
|
+
if (prefetchOn && !options.abortSignal?.aborted)
|
|
108411
|
+
prefetcher.start(event.id, event.name, event.input);
|
|
108412
|
+
break;
|
|
108074
108413
|
case "done":
|
|
108075
108414
|
break;
|
|
108076
108415
|
case "error":
|
|
@@ -108090,6 +108429,10 @@ Continue the work from here.` }] });
|
|
|
108090
108429
|
allowRestartAfterRender: !!options.onStreamRestart
|
|
108091
108430
|
}, onEvent);
|
|
108092
108431
|
options.onApiCallDuration?.(Date.now() - _apiCallStartedAt);
|
|
108432
|
+
if (depth === 0)
|
|
108433
|
+
_lastApiCallEndedAt.set(options.sessionId || PROCESS_BUDGET_KEY, Date.now());
|
|
108434
|
+
if (pendingRuntimeContext)
|
|
108435
|
+
persistRuntimeContext(messages, sentUserIdx, pendingRuntimeContext);
|
|
108093
108436
|
} catch (err) {
|
|
108094
108437
|
options.onApiCallDuration?.(Date.now() - _apiCallStartedAt);
|
|
108095
108438
|
if (options.abortSignal?.aborted || err.name === "AbortError") {
|
|
@@ -108244,6 +108587,7 @@ Continue the work from here.` }] });
|
|
|
108244
108587
|
stopReason = "clean";
|
|
108245
108588
|
break;
|
|
108246
108589
|
}
|
|
108590
|
+
const prefetchSafe = prefetchOn && (0, toolPrefetch_1.isPrefetchSafeMessage)(toolUseBlocks.map((b) => b.name));
|
|
108247
108591
|
const toolResults = await Promise.all(toolUseBlocks.map(async (block) => {
|
|
108248
108592
|
const { id, name, input } = block;
|
|
108249
108593
|
const toolMeta = { id };
|
|
@@ -108324,15 +108668,21 @@ Continue the work from here.` }] });
|
|
|
108324
108668
|
result = external;
|
|
108325
108669
|
} else if (options.mcpManager?.isMcpTool(name)) {
|
|
108326
108670
|
const mcpOutput = await stopAwaiting(options.mcpManager.callTool(name, input, options.abortSignal), options.abortSignal);
|
|
108327
|
-
result = mcpOutput === STOP_TIMEOUT_RESULT ? STOP_TIMEOUT_RESULT : { output: mcpOutput ?? "" };
|
|
108671
|
+
result = mcpOutput === STOP_TIMEOUT_RESULT ? STOP_TIMEOUT_RESULT : { output: (0, executor_1.capExternalOutput)(mcpOutput ?? "", `mcp-${name}`) };
|
|
108328
108672
|
} else {
|
|
108329
108673
|
options.checkpointManager?.recordBeforeMutation(name, input);
|
|
108330
108674
|
const onStream = options.onToolStreamChunk ? (chunk) => options.onToolStreamChunk(name, chunk, void 0, toolMeta) : void 0;
|
|
108331
108675
|
const run = () => (0, executor_1.executeTool)(name, input, options.abortSignal, sandboxCfg, options.workDir, agentScope, onStream, options.selfPeer);
|
|
108332
108676
|
const locks = name === "bash" ? (0, bashClassify_1.bashNeedsRepoLock)(String(input.command ?? "")) ? [REPO_STATE_LOCK] : [] : lockPathsFor(name, input, options.workDir);
|
|
108333
108677
|
const dedupeStub = name === "read_file" ? readDedupe.check(input, messages) : null;
|
|
108678
|
+
const prefetched = !dedupeStub && prefetchSafe ? prefetcher.take(id, name, input) : null;
|
|
108334
108679
|
if (dedupeStub) {
|
|
108335
108680
|
result = { output: dedupeStub };
|
|
108681
|
+
} else if (prefetched) {
|
|
108682
|
+
result = await prefetched;
|
|
108683
|
+
if (name === "read_file" && result.error === void 0 && result.output?.startsWith("[File:")) {
|
|
108684
|
+
readDedupe.record(input, id);
|
|
108685
|
+
}
|
|
108336
108686
|
} else {
|
|
108337
108687
|
result = locks.length ? await (0, crossProcessLock_1.withCrossProcessLocks)(locks, () => withFileLocks(locks, run), options.workDir) : await run();
|
|
108338
108688
|
if (name === "read_file" && result.error === void 0 && result.output?.startsWith("[File:")) {
|
|
@@ -156640,12 +156990,24 @@ function collectEnv(workDir) {
|
|
|
156640
156990
|
platform: `${os5.platform()} ${os5.release()}`,
|
|
156641
156991
|
shell: process.env.SHELL ?? process.env.ComSpec ?? "unknown",
|
|
156642
156992
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
156993
|
+
...collectGitEnv(workDir)
|
|
156994
|
+
};
|
|
156995
|
+
}
|
|
156996
|
+
function collectGitEnv(workDir) {
|
|
156997
|
+
return {
|
|
156643
156998
|
gitBranch: tryExec("git branch --show-current", workDir),
|
|
156644
156999
|
gitStatus: tryExec("git status --short", workDir),
|
|
156645
157000
|
gitDiff: tryExec("git diff --stat HEAD", workDir),
|
|
156646
157001
|
recentCommits: tryExec("git log --oneline -5", workDir)
|
|
156647
157002
|
};
|
|
156648
157003
|
}
|
|
157004
|
+
function refreshEnvForTurn(env4, workDir) {
|
|
157005
|
+
return {
|
|
157006
|
+
...env4,
|
|
157007
|
+
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
157008
|
+
...collectGitEnv(workDir)
|
|
157009
|
+
};
|
|
157010
|
+
}
|
|
156649
157011
|
var NEXRALL_MD_CANDIDATES = [
|
|
156650
157012
|
"nexrall.md",
|
|
156651
157013
|
"NEXRALL.md",
|
|
@@ -156878,7 +157240,7 @@ async function runTurn(messages, modelAlias, workDir, abortSignal, env4, nexrall
|
|
|
156878
157240
|
const result = await (0, import_code_core5.runAgentLoop)(messages, {
|
|
156879
157241
|
workDir,
|
|
156880
157242
|
model: modelAlias,
|
|
156881
|
-
env: env4,
|
|
157243
|
+
env: refreshEnvForTurn(env4, workDir),
|
|
156882
157244
|
nexrallMd,
|
|
156883
157245
|
mode,
|
|
156884
157246
|
// `/mode plan` previously only hinted to the backend — the footer said "plan
|
|
@@ -157087,7 +157449,7 @@ async function runTurnHeadless(messages, modelAlias, workDir, _abortSignal, env4
|
|
|
157087
157449
|
const result = await (0, import_code_core5.runAgentLoop)(messages, {
|
|
157088
157450
|
workDir,
|
|
157089
157451
|
model: modelAlias,
|
|
157090
|
-
env: env4,
|
|
157452
|
+
env: refreshEnvForTurn(env4, workDir),
|
|
157091
157453
|
nexrallMd,
|
|
157092
157454
|
mode,
|
|
157093
157455
|
planMode: mode === "plan",
|
|
@@ -157403,8 +157765,8 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
157403
157765
|
startRowCount();
|
|
157404
157766
|
}
|
|
157405
157767
|
if (options.showBanner !== false && !headless) {
|
|
157406
|
-
const branch =
|
|
157407
|
-
const gitStatus =
|
|
157768
|
+
const branch = env4.gitBranch;
|
|
157769
|
+
const gitStatus = env4.gitStatus;
|
|
157408
157770
|
const changedLines = gitStatus ? gitStatus.split("\n").filter(Boolean).length : 0;
|
|
157409
157771
|
const tips = ["Run /init to create a nexrall.md file with instructions for Nexrall Code."];
|
|
157410
157772
|
if (branch) {
|
|
@@ -157472,11 +157834,8 @@ Resume it with: nex --worktree ${worktreeState.name}
|
|
|
157472
157834
|
const compacted = await (0, import_code_core5.compactMessagesForResume)(messages, {
|
|
157473
157835
|
workDir,
|
|
157474
157836
|
model: modelAlias,
|
|
157475
|
-
clientType: "cli"
|
|
157476
|
-
|
|
157477
|
-
if (!headless)
|
|
157478
|
-
console.log(source_default.dim(text.trim()));
|
|
157479
|
-
}
|
|
157837
|
+
clientType: "cli"
|
|
157838
|
+
// Compaction is silent housekeeping — no "♻️ Auto-compacted …" line.
|
|
157480
157839
|
});
|
|
157481
157840
|
} catch {
|
|
157482
157841
|
}
|
|
@@ -157709,8 +158068,8 @@ ${text}` : "");
|
|
|
157709
158068
|
await (0, import_code_core5.compactMessagesForResume)(messages, {
|
|
157710
158069
|
workDir,
|
|
157711
158070
|
model: modelAlias,
|
|
157712
|
-
clientType: "cli"
|
|
157713
|
-
|
|
158071
|
+
clientType: "cli"
|
|
158072
|
+
// Silent housekeeping — no "♻️ Auto-compacted …" line.
|
|
157714
158073
|
});
|
|
157715
158074
|
} catch {
|
|
157716
158075
|
}
|