nolo-cli 0.159.0-alpha.4 → 0.160.0-alpha.1
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/{agentDeleteCommand-VXWLHIUC.js → agentDeleteCommand-ON2KVSJ5.js} +3 -3
- package/{agentEmailCommands-2TQN6UIZ.js → agentEmailCommands-2QPD5VP3.js} +4 -4
- package/{agentListCommands-44UDONIY.js → agentListCommands-L33M3I6V.js} +1 -1
- package/{agentMachineCommands-KH7OSRWP.js → agentMachineCommands-V44DPSED.js} +2 -2
- package/{agentRecordCommands-6BNH5KK2.js → agentRecordCommands-CKILCNQZ.js} +4 -4
- package/{agentRunCommand-7MFXU4GK.js → agentRunCommand-6IN7NK7H.js} +4 -4
- package/{agentRunControl-USFIAK7X.js → agentRunControl-XBSNHHZE.js} +1 -1
- package/{agentRuntimeLocal-BAQON6BB.js → agentRuntimeLocal-XCKO5FVP.js} +1 -1
- package/{appDeleteCommands-R73W7UJM.js → appDeleteCommands-2PJFNLAJ.js} +1 -1
- package/{appDeployCommands-F65F6N63.js → appDeployCommands-AZCMCMK6.js} +1 -1
- package/{appDeployStatusCommands-CTRCXJJX.js → appDeployStatusCommands-HSIKPVJN.js} +1 -1
- package/{appGetCommands-VTQERXLK.js → appGetCommands-IUZCPAP7.js} +1 -1
- package/{appListCommands-MY3WFDYA.js → appListCommands-JLFVS44M.js} +1 -1
- package/{chunk-HBW2XA3L.js → chunk-2XDQAWBM.js} +1 -1
- package/{chunk-YNOXGQ7X.js → chunk-EVPKKBSI.js} +2 -2
- package/{chunk-TK2AX7M6.js → chunk-JSB2OPQT.js} +68 -4
- package/{chunk-B5JIGIKM.js → chunk-K25WQPP3.js} +186 -28
- package/{chunk-QV3VGSX6.js → chunk-SNAWGDXT.js} +260 -1
- package/{chunk-SCQT4CRF.js → chunk-UY73HNIN.js} +4 -4
- package/{chunk-NWKPVIHL.js → chunk-ZSLIYVIQ.js} +1 -1
- package/{commandRegistry-3JCFSTBQ.js → commandRegistry-A4OR4B4L.js} +45 -45
- package/{dialogCommands-FDQPV6GO.js → dialogCommands-KMECTGCW.js} +3 -3
- package/{docCreateCommands-Z5KKWS2C.js → docCreateCommands-4IT5PUAL.js} +1 -1
- package/{docDeleteCommands-YTGMEQ4I.js → docDeleteCommands-QS66YNZV.js} +1 -1
- package/{docReadCommands-SK2CLD2S.js → docReadCommands-3SAI46YC.js} +1 -1
- package/{docUpdateCommands-SI4PL2L3.js → docUpdateCommands-OGYG5BRC.js} +1 -1
- package/index.js +3 -3
- package/{localRuntimeAdapter-TVIGJ3PU.js → localRuntimeAdapter-MO64KEOS.js} +3 -3
- package/{machineCommands-EYP73LBU.js → machineCommands-7MBJJY4K.js} +4 -4
- package/{machineWsRunDispatch-6QWYWIHP.js → machineWsRunDispatch-T4LFRJL3.js} +4 -4
- package/package.json +1 -1
- package/{readlineWorkspace-QBN246OU.js → readlineWorkspace-QHPB5LUC.js} +6 -43
- package/{spaceCommands-5WANPZMM.js → spaceCommands-WQMUCGV7.js} +1 -1
|
@@ -14050,8 +14050,11 @@ function detectExecShellSynchronousWarnings(command, shell) {
|
|
|
14050
14050
|
}
|
|
14051
14051
|
|
|
14052
14052
|
// packages/agent-runtime/workspaceShell.ts
|
|
14053
|
-
import {
|
|
14053
|
+
import { createWriteStream, mkdirSync as mkdirSync2 } from "node:fs";
|
|
14054
|
+
import { dirname, join as join4, resolve } from "node:path";
|
|
14054
14055
|
import { spawn as spawnChildProcess } from "node:child_process";
|
|
14056
|
+
import { randomUUID } from "node:crypto";
|
|
14057
|
+
import { tmpdir } from "node:os";
|
|
14055
14058
|
|
|
14056
14059
|
// packages/agent-runtime/runtimeCompat.ts
|
|
14057
14060
|
import { existsSync as existsSync2, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
@@ -14987,39 +14990,168 @@ function truncateToolOutput(value, limit = 2e4, options) {
|
|
|
14987
14990
|
${tail}`;
|
|
14988
14991
|
}
|
|
14989
14992
|
var DEFAULT_MAX_STREAM_BUFFER_BYTES = 5 * 1024 * 1024;
|
|
14990
|
-
function readNodeStream(stream,
|
|
14993
|
+
function readNodeStream(stream, maxBytesOrOptions = DEFAULT_MAX_STREAM_BUFFER_BYTES) {
|
|
14991
14994
|
if (!stream) return Promise.resolve("");
|
|
14995
|
+
const options = typeof maxBytesOrOptions === "number" ? { maxBytes: maxBytesOrOptions } : maxBytesOrOptions ?? {};
|
|
14996
|
+
const maxBytes = typeof options.maxBytes === "number" && Number.isFinite(options.maxBytes) && options.maxBytes >= 0 ? options.maxBytes : DEFAULT_MAX_STREAM_BUFFER_BYTES;
|
|
14997
|
+
const spillPath = asOptionalTrimmedString(options.spillPath);
|
|
14998
|
+
const createSink = options.spillSinkFactory ?? ((path) => createWriteStream(path));
|
|
14992
14999
|
return new Promise((resolveStream, rejectStream) => {
|
|
14993
15000
|
const chunks2 = [];
|
|
14994
15001
|
let totalBytes = 0;
|
|
14995
15002
|
let settled = false;
|
|
15003
|
+
let truncated = false;
|
|
15004
|
+
let spillState = spillPath ? "idle" : "disabled";
|
|
15005
|
+
let spillError = null;
|
|
15006
|
+
let spillSink = null;
|
|
15007
|
+
let sourcePausedForSpill = false;
|
|
15008
|
+
let sinkFinished = false;
|
|
14996
15009
|
const formatLimit = maxBytes >= 1024 * 1024 ? `${Math.round(maxBytes / (1024 * 1024))}MB` : `${Math.round(maxBytes / 1024)}KB`;
|
|
14997
|
-
const
|
|
15010
|
+
const resumeSourceIfPaused = () => {
|
|
15011
|
+
if (!sourcePausedForSpill) return;
|
|
15012
|
+
sourcePausedForSpill = false;
|
|
15013
|
+
try {
|
|
15014
|
+
stream.resume?.();
|
|
15015
|
+
} catch {
|
|
15016
|
+
}
|
|
15017
|
+
};
|
|
15018
|
+
const markSpillFailed = (error) => {
|
|
15019
|
+
if (spillState === "failed") return;
|
|
15020
|
+
spillState = "failed";
|
|
15021
|
+
if (!spillError) {
|
|
15022
|
+
spillError = toErrorMessage(error);
|
|
15023
|
+
}
|
|
15024
|
+
const sink = spillSink;
|
|
15025
|
+
spillSink = null;
|
|
15026
|
+
if (sink) {
|
|
15027
|
+
try {
|
|
15028
|
+
sink.destroy?.();
|
|
15029
|
+
} catch {
|
|
15030
|
+
}
|
|
15031
|
+
}
|
|
15032
|
+
resumeSourceIfPaused();
|
|
15033
|
+
};
|
|
15034
|
+
const writeToSink = (buf) => {
|
|
15035
|
+
const sink = spillSink;
|
|
15036
|
+
if (!sink || spillState !== "open") return;
|
|
15037
|
+
if (sink.destroyed === true) {
|
|
15038
|
+
markSpillFailed(new Error("spill writable closed before finish"));
|
|
15039
|
+
return;
|
|
15040
|
+
}
|
|
15041
|
+
let accepted = true;
|
|
15042
|
+
try {
|
|
15043
|
+
accepted = sink.write(buf) !== false;
|
|
15044
|
+
} catch (error) {
|
|
15045
|
+
markSpillFailed(error);
|
|
15046
|
+
return;
|
|
15047
|
+
}
|
|
15048
|
+
if (!accepted && !sourcePausedForSpill) {
|
|
15049
|
+
sourcePausedForSpill = true;
|
|
15050
|
+
try {
|
|
15051
|
+
stream.pause?.();
|
|
15052
|
+
} catch {
|
|
15053
|
+
sourcePausedForSpill = false;
|
|
15054
|
+
}
|
|
15055
|
+
}
|
|
15056
|
+
};
|
|
15057
|
+
const openSpill = (headChunks, crossingChunk) => {
|
|
15058
|
+
if (!spillPath || spillState !== "idle") return;
|
|
15059
|
+
let sink;
|
|
15060
|
+
try {
|
|
15061
|
+
mkdirSync2(dirname(spillPath), { recursive: true });
|
|
15062
|
+
sink = createSink(spillPath);
|
|
15063
|
+
sink.on("error", (error) => markSpillFailed(error));
|
|
15064
|
+
sink.on("drain", () => {
|
|
15065
|
+
if (settled) return;
|
|
15066
|
+
resumeSourceIfPaused();
|
|
15067
|
+
});
|
|
15068
|
+
sink.on("finish", () => {
|
|
15069
|
+
sinkFinished = true;
|
|
15070
|
+
});
|
|
15071
|
+
sink.on("close", () => {
|
|
15072
|
+
if (sinkFinished || spillState !== "open") return;
|
|
15073
|
+
markSpillFailed(new Error("spill writable closed before finish"));
|
|
15074
|
+
});
|
|
15075
|
+
} catch (error) {
|
|
15076
|
+
spillState = "failed";
|
|
15077
|
+
spillError = toErrorMessage(error);
|
|
15078
|
+
spillSink = null;
|
|
15079
|
+
return;
|
|
15080
|
+
}
|
|
15081
|
+
spillSink = sink;
|
|
15082
|
+
spillState = "open";
|
|
15083
|
+
for (const head3 of headChunks) writeToSink(head3);
|
|
15084
|
+
writeToSink(crossingChunk);
|
|
15085
|
+
};
|
|
15086
|
+
const finalize2 = (wasTruncated) => {
|
|
14998
15087
|
if (settled) return;
|
|
14999
15088
|
settled = true;
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
|
|
15089
|
+
const truncatedNow = wasTruncated || truncated;
|
|
15090
|
+
const baseText = Buffer.concat(chunks2).toString("utf8");
|
|
15091
|
+
const done4 = () => {
|
|
15092
|
+
let text2 = baseText;
|
|
15093
|
+
if (truncatedNow) {
|
|
15094
|
+
const notes = [`output exceeded ${formatLimit} buffer limit`];
|
|
15095
|
+
if (spillState === "ok") {
|
|
15096
|
+
notes.push(`full output: ${spillPath}`);
|
|
15097
|
+
} else if (spillPath) {
|
|
15098
|
+
notes.push(
|
|
15099
|
+
`spill failed${spillError ? ` (${spillError})` : ""}; output incomplete`
|
|
15100
|
+
);
|
|
15101
|
+
}
|
|
15102
|
+
text2 += `
|
|
15003
15103
|
|
|
15004
|
-
[stream pipe truncated:
|
|
15104
|
+
[stream pipe truncated: ${notes.join("; ")}]`;
|
|
15105
|
+
}
|
|
15106
|
+
resolveStream(text2);
|
|
15107
|
+
};
|
|
15108
|
+
const sink = spillSink;
|
|
15109
|
+
if (!sink || spillState !== "open") {
|
|
15110
|
+
done4();
|
|
15111
|
+
return;
|
|
15112
|
+
}
|
|
15113
|
+
let closed = false;
|
|
15114
|
+
const settleSink = (failed, error) => {
|
|
15115
|
+
if (closed) return;
|
|
15116
|
+
closed = true;
|
|
15117
|
+
if (failed) {
|
|
15118
|
+
markSpillFailed(error ?? new Error("spill write failed"));
|
|
15119
|
+
} else if (spillState === "open") {
|
|
15120
|
+
spillState = "ok";
|
|
15121
|
+
}
|
|
15122
|
+
done4();
|
|
15123
|
+
};
|
|
15124
|
+
if (sink.destroyed === true) {
|
|
15125
|
+
settleSink(true, new Error("spill writable closed before finish"));
|
|
15126
|
+
return;
|
|
15127
|
+
}
|
|
15128
|
+
sink.once("error", (error) => settleSink(true, error));
|
|
15129
|
+
sink.once("finish", () => settleSink(false));
|
|
15130
|
+
sink.once("close", () => {
|
|
15131
|
+
settleSink(!sinkFinished, new Error("spill writable closed before finish"));
|
|
15132
|
+
});
|
|
15133
|
+
try {
|
|
15134
|
+
sink.end?.();
|
|
15135
|
+
} catch (error) {
|
|
15136
|
+
settleSink(true, error);
|
|
15005
15137
|
}
|
|
15006
|
-
resolveStream(text2);
|
|
15007
15138
|
};
|
|
15008
15139
|
stream.on("data", (chunk) => {
|
|
15009
15140
|
if (settled) return;
|
|
15010
15141
|
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
15142
|
+
if (truncated) {
|
|
15143
|
+
writeToSink(buf);
|
|
15144
|
+
return;
|
|
15145
|
+
}
|
|
15011
15146
|
if (totalBytes + buf.length >= maxBytes) {
|
|
15012
15147
|
const remaining = Math.max(0, maxBytes - totalBytes);
|
|
15148
|
+
const headChunks = chunks2.slice();
|
|
15013
15149
|
if (remaining > 0) {
|
|
15014
15150
|
chunks2.push(buf.subarray(0, remaining));
|
|
15015
15151
|
}
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
}
|
|
15020
|
-
} catch {
|
|
15021
|
-
}
|
|
15022
|
-
finalize2(true);
|
|
15152
|
+
totalBytes += buf.length;
|
|
15153
|
+
truncated = true;
|
|
15154
|
+
openSpill(headChunks, buf);
|
|
15023
15155
|
return;
|
|
15024
15156
|
}
|
|
15025
15157
|
totalBytes += buf.length;
|
|
@@ -15028,6 +15160,19 @@ function readNodeStream(stream, maxBytes = DEFAULT_MAX_STREAM_BUFFER_BYTES) {
|
|
|
15028
15160
|
stream.on("error", (error) => {
|
|
15029
15161
|
if (settled) return;
|
|
15030
15162
|
settled = true;
|
|
15163
|
+
const sink = spillSink;
|
|
15164
|
+
spillSink = null;
|
|
15165
|
+
if (!spillError) spillError = toErrorMessage(error);
|
|
15166
|
+
if (spillState !== "failed" && spillState !== "disabled") {
|
|
15167
|
+
spillState = "failed";
|
|
15168
|
+
}
|
|
15169
|
+
if (sink) {
|
|
15170
|
+
try {
|
|
15171
|
+
sink.destroy?.();
|
|
15172
|
+
} catch {
|
|
15173
|
+
}
|
|
15174
|
+
}
|
|
15175
|
+
resumeSourceIfPaused();
|
|
15031
15176
|
rejectStream(error);
|
|
15032
15177
|
});
|
|
15033
15178
|
stream.on("end", () => finalize2(false));
|
|
@@ -15140,8 +15285,12 @@ async function runWorkspaceCommand(args2) {
|
|
|
15140
15285
|
process.removeListener("SIGINT", cleanupChildOnHostSignal);
|
|
15141
15286
|
};
|
|
15142
15287
|
exitPromise.then(detachSignalCleanup, detachSignalCleanup);
|
|
15143
|
-
const stdoutCapture = stdoutPromiseResult(
|
|
15144
|
-
|
|
15288
|
+
const stdoutCapture = stdoutPromiseResult(
|
|
15289
|
+
readNodeStream(proc.stdout, { spillPath: join4(tmpdir(), `nolo-stream-${randomUUID()}.log`) })
|
|
15290
|
+
);
|
|
15291
|
+
const stderrCapture = stdoutPromiseResult(
|
|
15292
|
+
readNodeStream(proc.stderr, { spillPath: join4(tmpdir(), `nolo-stream-${randomUUID()}-stderr.log`) })
|
|
15293
|
+
);
|
|
15145
15294
|
const killChild = (signal) => {
|
|
15146
15295
|
if (detached && typeof proc.pid === "number") {
|
|
15147
15296
|
try {
|
|
@@ -15550,11 +15699,11 @@ async function invokeCapability(capabilityOrName, input, ctx = {}) {
|
|
|
15550
15699
|
}
|
|
15551
15700
|
|
|
15552
15701
|
// packages/agent-runtime/localWorkspaceTools.ts
|
|
15553
|
-
import { existsSync as
|
|
15702
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
15554
15703
|
import { createHash as createHash4 } from "node:crypto";
|
|
15555
15704
|
import { lstat, mkdir, readdir as readdir2, readFile as readFile3, realpath, stat as stat3, writeFile } from "node:fs/promises";
|
|
15556
15705
|
import { homedir } from "node:os";
|
|
15557
|
-
import { dirname, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve4, sep } from "node:path";
|
|
15706
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve4, sep } from "node:path";
|
|
15558
15707
|
import { spawn as spawnChildProcess3 } from "node:child_process";
|
|
15559
15708
|
|
|
15560
15709
|
// packages/core/readRangeLedger.ts
|
|
@@ -16836,7 +16985,7 @@ function resolveRipgrepBinary(env = process.env) {
|
|
|
16836
16985
|
const fromEnv = asOptionalTrimmedString(env.NOLO_BUNDLED_RG);
|
|
16837
16986
|
if (fromEnv) {
|
|
16838
16987
|
try {
|
|
16839
|
-
if (
|
|
16988
|
+
if (existsSync4(fromEnv)) return fromEnv;
|
|
16840
16989
|
} catch {
|
|
16841
16990
|
}
|
|
16842
16991
|
}
|
|
@@ -16942,6 +17091,7 @@ ${tail}`,
|
|
|
16942
17091
|
};
|
|
16943
17092
|
}
|
|
16944
17093
|
var READ_FILE_LEDGER_MAX_RECORDS = 64;
|
|
17094
|
+
var READ_FILE_LEDGER_MAX_KEYS = 256;
|
|
16945
17095
|
async function readFileTool(args2) {
|
|
16946
17096
|
const parsed = parseWorkspaceToolArguments(args2.call.arguments);
|
|
16947
17097
|
const requestedPath = requireWorkspaceToolPath(parsed);
|
|
@@ -16980,6 +17130,8 @@ async function readFileTool(args2) {
|
|
|
16980
17130
|
const retainedCap = resolveHistoricalToolContentCap("readFile", 0);
|
|
16981
17131
|
const retained = filterRetainedLedgerRecords(entry.records, retainedCap);
|
|
16982
17132
|
if (retained.length > 0 && isLineRangeCovered(requestRange, retained)) {
|
|
17133
|
+
ledger.delete(relativePath);
|
|
17134
|
+
ledger.set(relativePath, entry);
|
|
16983
17135
|
return {
|
|
16984
17136
|
content: `[readFile] ${relativePath} lines ${requestRange.startLine}-${requestRange.endLine} were already delivered earlier and the file is unchanged; not resending. Pass force:true to refetch.`,
|
|
16985
17137
|
metadata: {
|
|
@@ -17012,10 +17164,16 @@ async function readFileTool(args2) {
|
|
|
17012
17164
|
const persistedChars = truncatedRead.content.length + "\n\n[tool metadata]\n".length + JSON.stringify(metadata).length;
|
|
17013
17165
|
const records = entry?.records ?? [];
|
|
17014
17166
|
records.push({ ...requestRange, chars: persistedChars });
|
|
17167
|
+
ledger.delete(relativePath);
|
|
17015
17168
|
ledger.set(relativePath, {
|
|
17016
17169
|
fingerprint,
|
|
17017
17170
|
records: records.slice(-READ_FILE_LEDGER_MAX_RECORDS)
|
|
17018
17171
|
});
|
|
17172
|
+
while (ledger.size > READ_FILE_LEDGER_MAX_KEYS) {
|
|
17173
|
+
const oldestKey = ledger.keys().next().value;
|
|
17174
|
+
if (oldestKey === void 0) break;
|
|
17175
|
+
ledger.delete(oldestKey);
|
|
17176
|
+
}
|
|
17019
17177
|
}
|
|
17020
17178
|
return { content: truncatedRead.content, metadata };
|
|
17021
17179
|
}
|
|
@@ -17028,7 +17186,7 @@ async function writeFileTool(args2) {
|
|
|
17028
17186
|
requestedPath,
|
|
17029
17187
|
...args2.confirmExternalFileAccess ? { confirmExternalFileAccess: args2.confirmExternalFileAccess } : {}
|
|
17030
17188
|
});
|
|
17031
|
-
await mkdir(
|
|
17189
|
+
await mkdir(dirname2(absolutePath), { recursive: true });
|
|
17032
17190
|
await writeFile(absolutePath, content, "utf8");
|
|
17033
17191
|
const relativePath = normalizeWorkspaceRelativePath({
|
|
17034
17192
|
workspaceRoot: resolve4(args2.workspaceRoot),
|
|
@@ -17485,7 +17643,7 @@ async function execShellTool(args2) {
|
|
|
17485
17643
|
);
|
|
17486
17644
|
}
|
|
17487
17645
|
var LAUNCH_PROCESS_STREAM_RING_CHARS = 65536;
|
|
17488
|
-
var LAUNCH_PROCESS_STREAM_CAPTURE_MAX_CHARS =
|
|
17646
|
+
var LAUNCH_PROCESS_STREAM_CAPTURE_MAX_CHARS = 1e6;
|
|
17489
17647
|
function createLaunchProcessStreamCapture() {
|
|
17490
17648
|
let ring = "";
|
|
17491
17649
|
let full = null;
|
|
@@ -18709,7 +18867,7 @@ var normalizeContextBlockScopes = (legacyBlocks = void 0, scopes = void 0) => {
|
|
|
18709
18867
|
};
|
|
18710
18868
|
|
|
18711
18869
|
// packages/agent-runtime/localAutoCompaction.ts
|
|
18712
|
-
import { randomUUID } from "node:crypto";
|
|
18870
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
18713
18871
|
function toPlanCompressionMessages(history) {
|
|
18714
18872
|
return history.map((message, index) => ({
|
|
18715
18873
|
id: typeof message.id === "string" && message.id.length > 0 ? message.id : `local-${index}`,
|
|
@@ -18944,7 +19102,7 @@ async function maybeAutoCompactLocalHistory(args2) {
|
|
|
18944
19102
|
};
|
|
18945
19103
|
}
|
|
18946
19104
|
emitPhase({ kind: "compaction-start" });
|
|
18947
|
-
const compactionAttemptId =
|
|
19105
|
+
const compactionAttemptId = randomUUID2();
|
|
18948
19106
|
let compactionT0 = Date.now();
|
|
18949
19107
|
let compactionInputTokens;
|
|
18950
19108
|
let compactionPrevSummaryTokens;
|
|
@@ -21787,7 +21945,7 @@ function resolveSessionKey(args2) {
|
|
|
21787
21945
|
}
|
|
21788
21946
|
|
|
21789
21947
|
// packages/agent-runtime/devin/devinProvider.ts
|
|
21790
|
-
import { randomBytes, randomUUID as
|
|
21948
|
+
import { randomBytes, randomUUID as randomUUID3 } from "node:crypto";
|
|
21791
21949
|
var CLIENT_NAME = "chisel";
|
|
21792
21950
|
var CLIENT_VERSION = "3000.11.3";
|
|
21793
21951
|
function writeVarint(fieldNum, value) {
|
|
@@ -21847,7 +22005,7 @@ function encodeDevinClientMetadata(token) {
|
|
|
21847
22005
|
]);
|
|
21848
22006
|
}
|
|
21849
22007
|
function devinId(id, purpose) {
|
|
21850
|
-
return id?.sessionKey && isStableSessionIdentityEnabled() ? deriveStableUuid(id.sessionKey, purpose) :
|
|
22008
|
+
return id?.sessionKey && isStableSessionIdentityEnabled() ? deriveStableUuid(id.sessionKey, purpose) : randomUUID3();
|
|
21851
22009
|
}
|
|
21852
22010
|
function encodeDevinChatMessage(msg, identity2, index = 0) {
|
|
21853
22011
|
const source = msg.role === "assistant" ? 2 : msg.role === "tool" ? 4 : 1;
|
|
@@ -21941,7 +22099,7 @@ ${item.text}`;
|
|
|
21941
22099
|
const chatMessageBuffers = coalesced.map((m, i) => encodeDevinChatMessage(m, identity2, i));
|
|
21942
22100
|
const completionConfig = buildCompletionConfig({ temperature });
|
|
21943
22101
|
const modelConfig = Buffer.concat([
|
|
21944
|
-
writeStringField(1,
|
|
22102
|
+
writeStringField(1, randomUUID3()),
|
|
21945
22103
|
writeVarint(2, 1),
|
|
21946
22104
|
writeVarint(3, 4)
|
|
21947
22105
|
]);
|
|
@@ -21953,7 +22111,7 @@ ${item.text}`;
|
|
|
21953
22111
|
writeMessageField(8, completionConfig),
|
|
21954
22112
|
...tools.map((tool) => writeMessageField(10, encodeDevinToolDefinition(tool))),
|
|
21955
22113
|
writeMessageField(15, modelConfig),
|
|
21956
|
-
writeStringField(16,
|
|
22114
|
+
writeStringField(16, randomUUID3()),
|
|
21957
22115
|
writeVarint(20, 1),
|
|
21958
22116
|
writeStringField(21, model)
|
|
21959
22117
|
]);
|
|
@@ -324,6 +324,233 @@ import { dirname, isAbsolute as isAbsolute2, join, resolve } from "node:path";
|
|
|
324
324
|
import * as nodeFs from "node:fs";
|
|
325
325
|
import { execFileSync as nodeExecFileSync, spawn as nodeSpawn } from "node:child_process";
|
|
326
326
|
|
|
327
|
+
// packages/cli/client/hostMemory.ts
|
|
328
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
329
|
+
import { freemem as osFreemem, totalmem as osTotalmem } from "node:os";
|
|
330
|
+
var PROC_MEMINFO_PATH = "/proc/meminfo";
|
|
331
|
+
var PROC_MOUNTS_PATH = "/proc/mounts";
|
|
332
|
+
var DEFAULT_CGROUP2_MOUNT = "/sys/fs/cgroup";
|
|
333
|
+
var SANDBOX_MARKER_PATHS = ["/.dockerenv", "/run/.containerenv"];
|
|
334
|
+
var PROC_SELF_CGROUP_PATH = "/proc/self/cgroup";
|
|
335
|
+
var SANDBOX_CGROUP_PATTERN = /(docker|kubepods|instabox|containerd)/;
|
|
336
|
+
var MEMORY_AVAILABLE_RATIO_THRESHOLD = 0.15;
|
|
337
|
+
var SWAP_USED_RATIO_THRESHOLD = 0.7;
|
|
338
|
+
var HOST_MEMORY_PRESSURE_HINT = "\u26A0 \u5185\u5B58\u504F\u7D27\uFF0C\u5EFA\u8BAE\u91CD\u6D3B\u653E\u6C99\u76D2/\u8FDC\u7AEF\u6216\u51CF\u5C11\u5E76\u53D1";
|
|
339
|
+
var BYTES_PER_MB = 1024 * 1024;
|
|
340
|
+
function toMbFromBytes(bytes) {
|
|
341
|
+
return Math.round(bytes / BYTES_PER_MB);
|
|
342
|
+
}
|
|
343
|
+
function kbToMb(kb) {
|
|
344
|
+
return Math.round(kb / 1024);
|
|
345
|
+
}
|
|
346
|
+
function tryReadText(deps, path) {
|
|
347
|
+
try {
|
|
348
|
+
const reader = deps.readFile ?? ((p) => readFileSync(p, "utf8"));
|
|
349
|
+
const text = reader(path);
|
|
350
|
+
return typeof text === "string" ? text : null;
|
|
351
|
+
} catch {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function tryExists(deps, path) {
|
|
356
|
+
try {
|
|
357
|
+
const checker = deps.exists ?? ((p) => existsSync(p));
|
|
358
|
+
return checker(path) === true;
|
|
359
|
+
} catch {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function readKbValue(text, key) {
|
|
364
|
+
const match = new RegExp(`^${key}:\\s*(\\d+)`, "m").exec(text);
|
|
365
|
+
if (!match) return null;
|
|
366
|
+
const value = Number.parseInt(match[1], 10);
|
|
367
|
+
return Number.isFinite(value) ? value : null;
|
|
368
|
+
}
|
|
369
|
+
function parseProcMeminfo(text) {
|
|
370
|
+
if (typeof text !== "string" || text.length === 0) return null;
|
|
371
|
+
const totalKb = readKbValue(text, "MemTotal");
|
|
372
|
+
const availableKb = readKbValue(text, "MemAvailable");
|
|
373
|
+
if (totalKb === null || availableKb === null) return null;
|
|
374
|
+
if (!(totalKb > 0)) return null;
|
|
375
|
+
const swapTotalKb = readKbValue(text, "SwapTotal") ?? 0;
|
|
376
|
+
const swapFreeKb = readKbValue(text, "SwapFree") ?? 0;
|
|
377
|
+
return {
|
|
378
|
+
source: "proc-meminfo",
|
|
379
|
+
totalMb: kbToMb(totalKb),
|
|
380
|
+
availableMb: kbToMb(Math.max(0, availableKb)),
|
|
381
|
+
swapTotalMb: kbToMb(Math.max(0, swapTotalKb)),
|
|
382
|
+
swapUsedMb: kbToMb(Math.max(0, swapTotalKb - swapFreeKb)),
|
|
383
|
+
hostAvailableMb: null
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
function detectSandbox(deps = {}) {
|
|
387
|
+
const platform = deps.platform ?? process.platform;
|
|
388
|
+
if (platform !== "linux") return false;
|
|
389
|
+
for (const marker of SANDBOX_MARKER_PATHS) {
|
|
390
|
+
if (tryExists(deps, marker)) return true;
|
|
391
|
+
}
|
|
392
|
+
const selfCgroup = tryReadText(deps, PROC_SELF_CGROUP_PATH);
|
|
393
|
+
return selfCgroup !== null && SANDBOX_CGROUP_PATTERN.test(selfCgroup);
|
|
394
|
+
}
|
|
395
|
+
function readOsView(deps) {
|
|
396
|
+
const os = deps.os ?? { totalmem: osTotalmem, freemem: osFreemem };
|
|
397
|
+
try {
|
|
398
|
+
const totalMb = toMbFromBytes(os.totalmem());
|
|
399
|
+
const availableMb = toMbFromBytes(os.freemem());
|
|
400
|
+
if (!(totalMb > 0) || !Number.isFinite(availableMb)) return null;
|
|
401
|
+
return {
|
|
402
|
+
source: "os",
|
|
403
|
+
totalMb,
|
|
404
|
+
availableMb: Math.max(0, availableMb),
|
|
405
|
+
// os 没有可移植的 swap 口径:按契约显示 n/a,而不是编一个数字。
|
|
406
|
+
swapTotalMb: null,
|
|
407
|
+
swapUsedMb: null,
|
|
408
|
+
hostAvailableMb: null
|
|
409
|
+
};
|
|
410
|
+
} catch {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function readHostView(deps) {
|
|
415
|
+
const platform = deps.platform ?? process.platform;
|
|
416
|
+
if (platform === "linux") {
|
|
417
|
+
const text = tryReadText(deps, PROC_MEMINFO_PATH);
|
|
418
|
+
if (text !== null) {
|
|
419
|
+
const parsed = parseProcMeminfo(text);
|
|
420
|
+
if (parsed) return parsed;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return readOsView(deps);
|
|
424
|
+
}
|
|
425
|
+
function parseCgroup2RelativePath(text) {
|
|
426
|
+
for (const line of text.split("\n")) {
|
|
427
|
+
const trimmed = line.trim();
|
|
428
|
+
if (!trimmed) continue;
|
|
429
|
+
const parts = trimmed.split(":");
|
|
430
|
+
if (parts.length < 3 || parts[0] !== "0" || parts[1] !== "") continue;
|
|
431
|
+
const path = parts.slice(2).join(":").trim();
|
|
432
|
+
if (!path) continue;
|
|
433
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
434
|
+
}
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
function parseCgroup2MountPoint(mountsText) {
|
|
438
|
+
for (const line of mountsText.split("\n")) {
|
|
439
|
+
const fields = line.trim().split(/\s+/);
|
|
440
|
+
if (fields.length < 3) continue;
|
|
441
|
+
if (fields[2] !== "cgroup2") continue;
|
|
442
|
+
const mountPoint = fields[1].replace(/\\040/g, " ");
|
|
443
|
+
if (mountPoint.startsWith("/")) return mountPoint;
|
|
444
|
+
}
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
function cgroupAncestorDirs(mountPoint, relativePath) {
|
|
448
|
+
const base = mountPoint.length > 1 && mountPoint.endsWith("/") ? mountPoint.slice(0, -1) : mountPoint;
|
|
449
|
+
const dirs = [];
|
|
450
|
+
if (relativePath && relativePath !== "/") {
|
|
451
|
+
const rel = relativePath.startsWith("/") ? relativePath : `/${relativePath}`;
|
|
452
|
+
const segments = rel.split("/").filter(Boolean);
|
|
453
|
+
for (let depth = segments.length; depth >= 1; depth -= 1) {
|
|
454
|
+
dirs.push(`${base}/${segments.slice(0, depth).join("/")}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
dirs.push(base);
|
|
458
|
+
return dirs;
|
|
459
|
+
}
|
|
460
|
+
function readCgroupMaxMb(deps, dir) {
|
|
461
|
+
const maxText = tryReadText(deps, `${dir}/memory.max`);
|
|
462
|
+
if (maxText === null) return null;
|
|
463
|
+
const maxRaw = maxText.trim();
|
|
464
|
+
if (maxRaw === "" || maxRaw === "max") return null;
|
|
465
|
+
const maxBytes = Number.parseInt(maxRaw, 10);
|
|
466
|
+
if (!Number.isFinite(maxBytes) || maxBytes <= 0) return null;
|
|
467
|
+
const totalMb = toMbFromBytes(maxBytes);
|
|
468
|
+
return totalMb > 0 ? totalMb : null;
|
|
469
|
+
}
|
|
470
|
+
function buildCgroupSnapshot(deps, dir, totalMb, hostView) {
|
|
471
|
+
const currentText = tryReadText(deps, `${dir}/memory.current`);
|
|
472
|
+
let usedMb = null;
|
|
473
|
+
if (currentText !== null) {
|
|
474
|
+
const currentBytes = Number.parseInt(currentText.trim(), 10);
|
|
475
|
+
if (Number.isFinite(currentBytes)) {
|
|
476
|
+
usedMb = Math.min(totalMb, Math.max(0, toMbFromBytes(currentBytes)));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
source: "cgroup",
|
|
481
|
+
totalMb,
|
|
482
|
+
availableMb: usedMb === null ? null : Math.max(0, totalMb - usedMb),
|
|
483
|
+
// swap 不是 cgroup 配额的一部分,只能借宿主视角(Linux 上就是 /proc/meminfo)。
|
|
484
|
+
swapTotalMb: hostView?.swapTotalMb ?? null,
|
|
485
|
+
swapUsedMb: hostView?.swapUsedMb ?? null,
|
|
486
|
+
hostAvailableMb: hostView?.availableMb ?? null
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function readCgroupLimitView(deps, hostView) {
|
|
490
|
+
const selfCgroupText = tryReadText(deps, PROC_SELF_CGROUP_PATH) ?? "";
|
|
491
|
+
const relativePath = parseCgroup2RelativePath(selfCgroupText);
|
|
492
|
+
const mountsText = tryReadText(deps, PROC_MOUNTS_PATH) ?? "";
|
|
493
|
+
const mountPoint = parseCgroup2MountPoint(mountsText) ?? DEFAULT_CGROUP2_MOUNT;
|
|
494
|
+
let limitingDir = null;
|
|
495
|
+
let limitingMb = Number.POSITIVE_INFINITY;
|
|
496
|
+
for (const dir of cgroupAncestorDirs(mountPoint, relativePath)) {
|
|
497
|
+
const totalMb = readCgroupMaxMb(deps, dir);
|
|
498
|
+
if (totalMb === null) continue;
|
|
499
|
+
if (totalMb < limitingMb) {
|
|
500
|
+
limitingMb = totalMb;
|
|
501
|
+
limitingDir = dir;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (limitingDir === null) return null;
|
|
505
|
+
return buildCgroupSnapshot(deps, limitingDir, limitingMb, hostView);
|
|
506
|
+
}
|
|
507
|
+
function readHostMemory(deps = {}) {
|
|
508
|
+
const platform = deps.platform ?? process.platform;
|
|
509
|
+
if (platform !== "linux") {
|
|
510
|
+
return readHostView(deps);
|
|
511
|
+
}
|
|
512
|
+
const hostView = readHostView(deps);
|
|
513
|
+
const cgroupView = readCgroupLimitView(deps, hostView);
|
|
514
|
+
if (!cgroupView) return hostView;
|
|
515
|
+
return {
|
|
516
|
+
...cgroupView,
|
|
517
|
+
scope: detectSandbox(deps) ? "sandbox" : "cgroup-limit"
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function isHostMemoryTight(mem) {
|
|
521
|
+
if (!(mem.totalMb > 0)) return false;
|
|
522
|
+
if (mem.availableMb !== null && mem.availableMb / mem.totalMb < MEMORY_AVAILABLE_RATIO_THRESHOLD) {
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
if (mem.swapTotalMb !== null && mem.swapUsedMb !== null && mem.swapTotalMb > 0 && mem.swapUsedMb / mem.swapTotalMb > SWAP_USED_RATIO_THRESHOLD) {
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
function formatHostMemoryMb(mb) {
|
|
531
|
+
const value = Math.max(0, Math.round(Number.isFinite(mb) ? mb : 0));
|
|
532
|
+
if (value >= 1024) return `${(value / 1024).toFixed(1)}G`;
|
|
533
|
+
return `${value}M`;
|
|
534
|
+
}
|
|
535
|
+
function formatSwapPart(mem) {
|
|
536
|
+
if (mem.swapTotalMb === null || mem.swapUsedMb === null) return "swap n/a";
|
|
537
|
+
return `swap ${formatHostMemoryMb(mem.swapUsedMb)}/${formatHostMemoryMb(mem.swapTotalMb)}`;
|
|
538
|
+
}
|
|
539
|
+
function formatHostMemoryLine(mem) {
|
|
540
|
+
const usedMb = mem.availableMb === null ? null : Math.max(0, mem.totalMb - mem.availableMb);
|
|
541
|
+
let line;
|
|
542
|
+
if (mem.source === "cgroup") {
|
|
543
|
+
const hostAvailable = mem.hostAvailableMb === null ? "n/a" : formatHostMemoryMb(mem.hostAvailableMb);
|
|
544
|
+
const prefix = (mem.scope ?? "sandbox") === "cgroup-limit" ? "[\u9650\u989D] \u672C\u8FDB\u7A0B\u5185\u5B58" : "[sandbox] \u5BB9\u5668\u5185\u5B58";
|
|
545
|
+
const usage = usedMb === null ? "\u5360\u7528\u672A\u77E5" : formatHostMemoryMb(usedMb);
|
|
546
|
+
line = `${prefix} ${usage}/${formatHostMemoryMb(mem.totalMb)} \xB7 \u5BBF\u4E3B\u53EF\u7528 ${hostAvailable}`;
|
|
547
|
+
} else {
|
|
548
|
+
const available = mem.availableMb === null ? "n/a" : formatHostMemoryMb(mem.availableMb);
|
|
549
|
+
line = `\u672C\u5730\u5185\u5B58 ${formatHostMemoryMb(usedMb ?? 0)}/${formatHostMemoryMb(mem.totalMb)}\uFF08\u53EF\u7528 ${available}\uFF09\xB7 ${formatSwapPart(mem)}`;
|
|
550
|
+
}
|
|
551
|
+
return isHostMemoryTight(mem) ? `${line} \xB7 ${HOST_MEMORY_PRESSURE_HINT}` : line;
|
|
552
|
+
}
|
|
553
|
+
|
|
327
554
|
// packages/cli/client/localRuntimeHelpers.ts
|
|
328
555
|
var REMOTE_DIALOG_SYNC_TIMEOUT_MS = 1e4;
|
|
329
556
|
var remoteDialogSyncTimeoutMsForTest;
|
|
@@ -1183,6 +1410,29 @@ function buildAgentRunChildCommand(options, deps = {}) {
|
|
|
1183
1410
|
}
|
|
1184
1411
|
return { execPath, childArgs: [entrypoint, ...commandParts, ...strippedArgs] };
|
|
1185
1412
|
}
|
|
1413
|
+
function safeReadHostMemory(reader) {
|
|
1414
|
+
try {
|
|
1415
|
+
return reader();
|
|
1416
|
+
} catch {
|
|
1417
|
+
return null;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
function emitHostMemoryNotice(mem, output) {
|
|
1421
|
+
if (!mem || !output) return void 0;
|
|
1422
|
+
let notice;
|
|
1423
|
+
try {
|
|
1424
|
+
notice = formatHostMemoryLine(mem);
|
|
1425
|
+
} catch {
|
|
1426
|
+
return void 0;
|
|
1427
|
+
}
|
|
1428
|
+
try {
|
|
1429
|
+
output.write(`${notice}
|
|
1430
|
+
`);
|
|
1431
|
+
} catch {
|
|
1432
|
+
return notice;
|
|
1433
|
+
}
|
|
1434
|
+
return notice;
|
|
1435
|
+
}
|
|
1186
1436
|
async function spawnLocalBackgroundRun(input, deps = {}) {
|
|
1187
1437
|
const env = deps.env ?? process.env;
|
|
1188
1438
|
const homedir = deps.homedir ?? nodeHomedir;
|
|
@@ -1266,6 +1516,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
|
|
|
1266
1516
|
NOLO_AGENT_RUN_CHILD: "1",
|
|
1267
1517
|
NOLO_AGENT_RUN_ID: runId
|
|
1268
1518
|
};
|
|
1519
|
+
const hostMemory = safeReadHostMemory(deps.readHostMemory ?? readHostMemory);
|
|
1269
1520
|
const logFd = fs.openSync(logPath, "a");
|
|
1270
1521
|
const proc = spawn(execPath, childArgs, {
|
|
1271
1522
|
cwd: input.cwd,
|
|
@@ -1283,6 +1534,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
|
|
|
1283
1534
|
proc.channel?.unref?.();
|
|
1284
1535
|
}
|
|
1285
1536
|
proc.unref();
|
|
1537
|
+
const hostMemoryNotice = emitHostMemoryNotice(hostMemory, input.output);
|
|
1286
1538
|
if (typeof proc.pid === "number") {
|
|
1287
1539
|
const processStartedAt = (deps.getProcessStartTime ?? defaultGetProcessStartTime)(proc.pid);
|
|
1288
1540
|
withRunRecordLock(runId, deps, () => {
|
|
@@ -1292,7 +1544,14 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
|
|
|
1292
1544
|
writeRunRecord(latest, deps);
|
|
1293
1545
|
});
|
|
1294
1546
|
}
|
|
1295
|
-
return {
|
|
1547
|
+
return {
|
|
1548
|
+
runId,
|
|
1549
|
+
pid: proc.pid,
|
|
1550
|
+
logPath,
|
|
1551
|
+
queuePath,
|
|
1552
|
+
batchId,
|
|
1553
|
+
...hostMemoryNotice ? { hostMemoryNotice } : {}
|
|
1554
|
+
};
|
|
1296
1555
|
}
|
|
1297
1556
|
function ackRunRecord(runId, deps = {}) {
|
|
1298
1557
|
withRunRecordLock(runId, deps, () => {
|
|
@@ -170,7 +170,7 @@ import {
|
|
|
170
170
|
runExecShellGates,
|
|
171
171
|
validateConfiguredRootExecutionLease,
|
|
172
172
|
verifyOwnerRouteAck
|
|
173
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-K25WQPP3.js";
|
|
174
174
|
import {
|
|
175
175
|
accumulateGeminiChunks,
|
|
176
176
|
buildGeminiGenerateContentRequest,
|
|
@@ -298,7 +298,7 @@ import {
|
|
|
298
298
|
terminateRunProcess,
|
|
299
299
|
transitionRunToTerminal,
|
|
300
300
|
withQueueLock
|
|
301
|
-
} from "./chunk-
|
|
301
|
+
} from "./chunk-SNAWGDXT.js";
|
|
302
302
|
import {
|
|
303
303
|
TASK_PREVIEW_MAX,
|
|
304
304
|
formatListRunsCard,
|
|
@@ -10766,7 +10766,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10766
10766
|
const recordRunExecutionIsolation = async () => {
|
|
10767
10767
|
try {
|
|
10768
10768
|
const { writeFileSync: writeFileSync4, mkdirSync: mkdirSync4 } = await import("node:fs");
|
|
10769
|
-
const { resolveRunsDir } = await import("./agentRunControl-
|
|
10769
|
+
const { resolveRunsDir } = await import("./agentRunControl-XBSNHHZE.js");
|
|
10770
10770
|
const fact = resolveLocalRunExecutionIsolationFact({
|
|
10771
10771
|
// F1:显式点名宿主执行的 run 在审计里必须与 docker 沙盒区分开
|
|
10772
10772
|
// (reason: host-explicit-writes vs docker-workload)。
|
|
@@ -10798,7 +10798,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
10798
10798
|
dockerWorkloadReleased = true;
|
|
10799
10799
|
dockerWorkloadLoad = null;
|
|
10800
10800
|
if (loaded) {
|
|
10801
|
-
const { resolveRunsDir } = await import("./agentRunControl-
|
|
10801
|
+
const { resolveRunsDir } = await import("./agentRunControl-XBSNHHZE.js");
|
|
10802
10802
|
const exportRunDiff = deps.exportDockerRunDiffArtifact ?? exportDockerRunDiffArtifact;
|
|
10803
10803
|
const warn = (message) => process.stderr.write(`[nolo] ${message}
|
|
10804
10804
|
`);
|