@opengeni/runtime 0.13.11 → 0.13.13
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/{chunk-RHB7ETON.js → chunk-3NUSY22C.js} +196 -41
- package/dist/chunk-3NUSY22C.js.map +1 -0
- package/dist/{index-Ciehex_q.d.ts → index-BraazrAO.d.ts} +13 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +1 -1
- package/package.json +3 -3
- package/src/sandbox/channel-a.ts +222 -39
- package/src/sandbox/index.ts +5 -5
- package/dist/chunk-RHB7ETON.js.map +0 -1
|
@@ -21427,6 +21427,8 @@ var REPOSITORY_DISCOVERY_STATUS_PREFIX = "__OPENGENI_REPOSITORY_DISCOVERY_STATUS
|
|
|
21427
21427
|
var NUL = String.fromCharCode(0);
|
|
21428
21428
|
var FS_LIST_TRUNCATED_MARKER = "__OPENGENI_FS_LIST_TRUNCATED__";
|
|
21429
21429
|
var FS_LIST_MAX_OUTPUT_BYTES = 768 * 1024;
|
|
21430
|
+
var GIT_COMMAND_CHUNK_BYTES = 512 * 1024;
|
|
21431
|
+
var GIT_METADATA_MAX_BYTES = 2 * 1024 * 1024;
|
|
21430
21432
|
var US = String.fromCharCode(31);
|
|
21431
21433
|
var RS = String.fromCharCode(30);
|
|
21432
21434
|
var SELFHOSTED_VIRTUAL_ROOT2 = "/workspace";
|
|
@@ -21467,8 +21469,9 @@ var SandboxChannelAService = class {
|
|
|
21467
21469
|
// ════════════════════════════ exec primitive ══════════════════════════════
|
|
21468
21470
|
// RAW exec — returns {stdout, stderr, exitCode}. Uses session.exec when present
|
|
21469
21471
|
// (the local/docker sessions return raw output); falls back to execCommand +
|
|
21470
|
-
// a banner strip
|
|
21471
|
-
//
|
|
21472
|
+
// a banner strip. Callers that parse output must independently bound/frame it
|
|
21473
|
+
// because provider retained-output truncation drops command prefixes. Throws
|
|
21474
|
+
// ChannelAUnsupportedError when neither exists.
|
|
21472
21475
|
async run(args) {
|
|
21473
21476
|
const withRunAs = this.runAs ? { ...args, runAs: this.runAs } : args;
|
|
21474
21477
|
if (this.session.exec) {
|
|
@@ -21907,6 +21910,121 @@ var SandboxChannelAService = class {
|
|
|
21907
21910
|
return { path, revision: this.revision };
|
|
21908
21911
|
}
|
|
21909
21912
|
// ════════════════════════════ Git (A2, read-only) ═════════════════════════
|
|
21913
|
+
/** Measure one Git command without returning its potentially large or
|
|
21914
|
+
* NUL-bearing output through the provider's text transport. */
|
|
21915
|
+
async measureConfinedCommandBytes(repo, command) {
|
|
21916
|
+
const measured = await this.runInConfinedDirectory(repo, {
|
|
21917
|
+
cmd: [
|
|
21918
|
+
"set -o pipefail",
|
|
21919
|
+
`{ ${command}; } 2>/dev/null | { bytes=$(wc -c | tr -d ' \\n'); printf '%s' "$bytes"; }`,
|
|
21920
|
+
"producer_status=${PIPESTATUS[0]}",
|
|
21921
|
+
`printf '\\t%s\\n' "$producer_status"`
|
|
21922
|
+
].join("; "),
|
|
21923
|
+
maxOutputTokens: 1024
|
|
21924
|
+
});
|
|
21925
|
+
const match = measured.stdout.match(/^(\d+)\t(\d+)\n?$/);
|
|
21926
|
+
if (!match || measured.exitCode !== null && measured.exitCode !== 0 || Number(match[2]) !== 0) {
|
|
21927
|
+
throw new ChannelAUnavailableError(
|
|
21928
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21929
|
+
);
|
|
21930
|
+
}
|
|
21931
|
+
const size = Number(match[1]);
|
|
21932
|
+
if (!Number.isSafeInteger(size) || size < 0) {
|
|
21933
|
+
throw new ChannelAUnavailableError(
|
|
21934
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21935
|
+
);
|
|
21936
|
+
}
|
|
21937
|
+
return size;
|
|
21938
|
+
}
|
|
21939
|
+
/** Read an exact prefix of a command's output in chunks that remain below
|
|
21940
|
+
* every supported execCommand retained-output ceiling. The producer is
|
|
21941
|
+
* intentionally rerun per chunk; turn-end capture calls this only after the
|
|
21942
|
+
* durable mutation authority has quiesced the workspace. */
|
|
21943
|
+
async readConfinedCommandPrefix(repo, command, byteLength2) {
|
|
21944
|
+
if (byteLength2 === 0) return Buffer.alloc(0);
|
|
21945
|
+
const chunks = [];
|
|
21946
|
+
for (let offset = 0; offset < byteLength2; offset += GIT_COMMAND_CHUNK_BYTES) {
|
|
21947
|
+
const expected = Math.min(GIT_COMMAND_CHUNK_BYTES, byteLength2 - offset);
|
|
21948
|
+
const chunk = await this.runInConfinedDirectory(repo, {
|
|
21949
|
+
cmd: [
|
|
21950
|
+
`{ ${command}; } 2>/dev/null`,
|
|
21951
|
+
`tail -c +${offset + 1}`,
|
|
21952
|
+
`head -c ${expected}`,
|
|
21953
|
+
"base64",
|
|
21954
|
+
`tr -d '\\n'`
|
|
21955
|
+
].join(" | "),
|
|
21956
|
+
maxOutputTokens: Math.ceil(GIT_COMMAND_CHUNK_BYTES * 4 / 3) + 1024
|
|
21957
|
+
});
|
|
21958
|
+
if (chunk.exitCode !== null && chunk.exitCode !== 0) {
|
|
21959
|
+
throw new ChannelAUnavailableError(
|
|
21960
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21961
|
+
);
|
|
21962
|
+
}
|
|
21963
|
+
const encoded = chunk.stdout.replace(/\s/g, "");
|
|
21964
|
+
const bytes = Buffer.from(encoded, "base64");
|
|
21965
|
+
if (bytes.byteLength !== expected || bytes.toString("base64") !== encoded) {
|
|
21966
|
+
throw new ChannelAUnavailableError(
|
|
21967
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
21968
|
+
);
|
|
21969
|
+
}
|
|
21970
|
+
chunks.push(bytes);
|
|
21971
|
+
}
|
|
21972
|
+
return Buffer.concat(chunks, byteLength2);
|
|
21973
|
+
}
|
|
21974
|
+
async readConfinedCommandBytes(repo, command, maxBytes) {
|
|
21975
|
+
const sizeBytes = await this.measureConfinedCommandBytes(repo, command);
|
|
21976
|
+
if (sizeBytes > maxBytes) {
|
|
21977
|
+
return { bytes: Buffer.alloc(0), sizeBytes, truncated: true };
|
|
21978
|
+
}
|
|
21979
|
+
return {
|
|
21980
|
+
bytes: await this.readConfinedCommandPrefix(repo, command, sizeBytes),
|
|
21981
|
+
sizeBytes,
|
|
21982
|
+
truncated: false
|
|
21983
|
+
};
|
|
21984
|
+
}
|
|
21985
|
+
/** Read a regular untracked file without routing its body through one large
|
|
21986
|
+
* execCommand response. Native provider reads are binary-safe; providers
|
|
21987
|
+
* without that surface use the same bounded chunk protocol as Git patches. */
|
|
21988
|
+
async readUntrackedRegularFile(repo, target, byteLength2) {
|
|
21989
|
+
if (byteLength2 === 0) return Buffer.alloc(0);
|
|
21990
|
+
const path = repo ? `${repo}/${target}` : target;
|
|
21991
|
+
assertSafeRelPath(path);
|
|
21992
|
+
if (this.session.readFile) {
|
|
21993
|
+
try {
|
|
21994
|
+
const raw = await this.session.readFile({
|
|
21995
|
+
path: this.joinRoot(path),
|
|
21996
|
+
maxBytes: byteLength2,
|
|
21997
|
+
...this.runAs ? { runAs: this.runAs } : {}
|
|
21998
|
+
});
|
|
21999
|
+
const bytes = typeof raw === "string" ? Buffer.from(raw, "utf8") : Buffer.from(raw);
|
|
22000
|
+
if (bytes.byteLength !== byteLength2) {
|
|
22001
|
+
throw new ChannelAUnavailableError(
|
|
22002
|
+
"Workspace Git data changed during capture. Retry the operation."
|
|
22003
|
+
);
|
|
22004
|
+
}
|
|
22005
|
+
return bytes;
|
|
22006
|
+
} catch (error) {
|
|
22007
|
+
if (error instanceof ChannelAUnavailableError) throw error;
|
|
22008
|
+
if (isWorkspaceEscapeError(error)) {
|
|
22009
|
+
throw new ChannelAValidationError(`path resolves outside workspace: ${path}`);
|
|
22010
|
+
}
|
|
22011
|
+
if (isDefinitePathNotFoundError(error)) {
|
|
22012
|
+
throw new ChannelANotFoundError(`file not found: ${path}`);
|
|
22013
|
+
}
|
|
22014
|
+
if (!this.session.exec && !this.session.execCommand) {
|
|
22015
|
+
throw new ChannelAUnavailableError(
|
|
22016
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22017
|
+
);
|
|
22018
|
+
}
|
|
22019
|
+
}
|
|
22020
|
+
}
|
|
22021
|
+
const fileArg = target.startsWith("./") ? target : `./${target}`;
|
|
22022
|
+
return await this.readConfinedCommandPrefix(
|
|
22023
|
+
repo,
|
|
22024
|
+
`file=${shellQuote6(fileArg)}; test ! -L "$file" && test -f "$file" || exit 66; cat -- "$file"`,
|
|
22025
|
+
byteLength2
|
|
22026
|
+
);
|
|
22027
|
+
}
|
|
21910
22028
|
async gitStatus(req) {
|
|
21911
22029
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
21912
22030
|
const inside = await this.runInConfinedDirectory(repo, {
|
|
@@ -21924,23 +22042,45 @@ var SandboxChannelAService = class {
|
|
|
21924
22042
|
revision: this.revision
|
|
21925
22043
|
};
|
|
21926
22044
|
}
|
|
21927
|
-
const
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
22045
|
+
const status = await this.readConfinedCommandBytes(
|
|
22046
|
+
repo,
|
|
22047
|
+
"git status --porcelain=v2 --branch -z",
|
|
22048
|
+
GIT_METADATA_MAX_BYTES
|
|
22049
|
+
);
|
|
22050
|
+
if (status.truncated) {
|
|
22051
|
+
throw new ChannelAUnavailableError(
|
|
22052
|
+
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22053
|
+
);
|
|
22054
|
+
}
|
|
22055
|
+
return { ...parsePorcelainV2(status.bytes.toString("utf8")), revision: this.revision };
|
|
21931
22056
|
}
|
|
21932
22057
|
async gitDiff(req) {
|
|
21933
22058
|
const repo = assertSafeRelPathOrRoot(req.path);
|
|
21934
22059
|
const ctx = req.contextLines;
|
|
21935
22060
|
let range = "";
|
|
21936
22061
|
if (req.fromRef && req.toRef) range = `${shellQuote6(req.fromRef)} ${shellQuote6(req.toRef)}`;
|
|
21937
|
-
else if (req.fromRef)
|
|
21938
|
-
|
|
22062
|
+
else if (req.fromRef) {
|
|
22063
|
+
if (req.fromRef === "HEAD") {
|
|
22064
|
+
const head = await this.runInConfinedDirectory(repo, {
|
|
22065
|
+
cmd: "if git rev-parse --verify --quiet HEAD >/dev/null; then printf 'present'; else printf 'unborn'; fi"
|
|
22066
|
+
});
|
|
22067
|
+
range = head.stdout.trim() === "present" ? shellQuote6(req.fromRef) : "--cached";
|
|
22068
|
+
} else {
|
|
22069
|
+
range = shellQuote6(req.fromRef);
|
|
22070
|
+
}
|
|
22071
|
+
} else if (req.staged) range = "--cached";
|
|
21939
22072
|
const pathspec = req.pathspec.length ? ` -- ${req.pathspec.map(shellQuote6).join(" ")}` : "";
|
|
21940
|
-
const numstat = await this.
|
|
21941
|
-
|
|
21942
|
-
|
|
21943
|
-
|
|
22073
|
+
const numstat = await this.readConfinedCommandBytes(
|
|
22074
|
+
repo,
|
|
22075
|
+
`git -c core.quotePath=false diff --no-color -z --numstat ${range}${pathspec}`.trim(),
|
|
22076
|
+
GIT_METADATA_MAX_BYTES
|
|
22077
|
+
);
|
|
22078
|
+
if (numstat.truncated) {
|
|
22079
|
+
throw new ChannelAUnavailableError(
|
|
22080
|
+
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22081
|
+
);
|
|
22082
|
+
}
|
|
22083
|
+
const stats = parseNumstatZ(numstat.bytes.toString("utf8"));
|
|
21944
22084
|
const files = [];
|
|
21945
22085
|
for (const stat4 of stats) {
|
|
21946
22086
|
const target = stat4.newPath;
|
|
@@ -21959,11 +22099,12 @@ var SandboxChannelAService = class {
|
|
|
21959
22099
|
});
|
|
21960
22100
|
continue;
|
|
21961
22101
|
}
|
|
21962
|
-
const patch = await this.
|
|
21963
|
-
|
|
21964
|
-
|
|
21965
|
-
|
|
21966
|
-
|
|
22102
|
+
const patch = await this.readConfinedCommandBytes(
|
|
22103
|
+
repo,
|
|
22104
|
+
`git -c core.quotePath=false diff --no-color -U${ctx} ${range} -- ${shellQuote6(target)}`.trim(),
|
|
22105
|
+
req.maxBytesPerFile
|
|
22106
|
+
);
|
|
22107
|
+
const parsed = patch.truncated ? { hunks: [], status: "modified" } : parseUnifiedPatch(patch.bytes.toString("utf8"));
|
|
21967
22108
|
files.push({
|
|
21968
22109
|
path: target,
|
|
21969
22110
|
oldPath: stat4.oldPath,
|
|
@@ -21973,49 +22114,63 @@ var SandboxChannelAService = class {
|
|
|
21973
22114
|
additions: stat4.additions,
|
|
21974
22115
|
deletions: stat4.deletions,
|
|
21975
22116
|
hunks: parsed.hunks,
|
|
21976
|
-
truncated:
|
|
22117
|
+
truncated: patch.truncated
|
|
21977
22118
|
});
|
|
21978
22119
|
}
|
|
21979
22120
|
if (req.includeUntracked) {
|
|
21980
|
-
const untracked = await this.
|
|
21981
|
-
|
|
21982
|
-
|
|
21983
|
-
|
|
22121
|
+
const untracked = await this.readConfinedCommandBytes(
|
|
22122
|
+
repo,
|
|
22123
|
+
`git -c core.quotePath=false ls-files --others --exclude-standard -z${pathspec}`,
|
|
22124
|
+
GIT_METADATA_MAX_BYTES
|
|
22125
|
+
);
|
|
22126
|
+
if (untracked.truncated) {
|
|
22127
|
+
throw new ChannelAUnavailableError(
|
|
22128
|
+
"Workspace Git metadata exceeded the safe capture limit. Retry with a narrower path."
|
|
22129
|
+
);
|
|
22130
|
+
}
|
|
22131
|
+
for (const target of untracked.bytes.toString("utf8").split(NUL).filter(Boolean)) {
|
|
21984
22132
|
const fileArg = target.startsWith("./") ? target : `./${target}`;
|
|
21985
22133
|
const read = await this.runInConfinedDirectory(repo, {
|
|
21986
22134
|
cmd: [
|
|
21987
22135
|
`file=${shellQuote6(fileArg)}`,
|
|
21988
|
-
'if [ -L "$file" ]; then printf "L\\
|
|
22136
|
+
'if [ -L "$file" ]; then printf "L\\t"; readlink -z -- "$file" | base64 | tr -d "\\n"; exit; fi',
|
|
21989
22137
|
'size=$(wc -c < "$file") || exit 66',
|
|
21990
22138
|
'line_count=$(wc -l < "$file") || exit 66',
|
|
21991
22139
|
'if [ "$size" -gt 0 ]; then last_byte=$(tail -c 1 "$file" | od -An -tu1 | tr -d " \\n"); if [ "$last_byte" != "10" ]; then line_count=$((line_count + 1)); fi; fi',
|
|
21992
|
-
'printf "F\\t%s\\t%s
|
|
21993
|
-
`head -c ${req.maxBytesPerFile + 1} "$file" | base64 | tr -d "\\n"`
|
|
22140
|
+
'printf "F\\t%s\\t%s" "$size" "$line_count"'
|
|
21994
22141
|
].join("; ")
|
|
21995
22142
|
});
|
|
21996
|
-
if (read.exitCode !== null && read.exitCode !== 0)
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
22143
|
+
if (read.exitCode !== null && read.exitCode !== 0) {
|
|
22144
|
+
throw new ChannelAUnavailableError(
|
|
22145
|
+
"Workspace Git data is temporarily unavailable. Retry the operation."
|
|
22146
|
+
);
|
|
22147
|
+
}
|
|
22148
|
+
const [kind, first, second] = read.stdout.split(" ");
|
|
22149
|
+
let sampled = Buffer.alloc(0);
|
|
22002
22150
|
let sizeBytes;
|
|
22003
22151
|
let lineCount;
|
|
22004
|
-
if (
|
|
22152
|
+
if (kind === "L") {
|
|
22153
|
+
const encoded = (first ?? "").replace(/\s/g, "");
|
|
22154
|
+
sampled = Buffer.from(encoded, "base64");
|
|
22005
22155
|
if (sampled.at(-1) !== 0) continue;
|
|
22006
22156
|
sampled = sampled.subarray(0, -1);
|
|
22007
22157
|
sizeBytes = sampled.length;
|
|
22008
22158
|
lineCount = addedLines(sampled).length;
|
|
22009
22159
|
} else {
|
|
22010
|
-
const [kind, sizeRaw, lineCountRaw] = header.split(" ");
|
|
22011
22160
|
if (kind !== "F") continue;
|
|
22012
|
-
const parsedSize = safeInt(
|
|
22013
|
-
const parsedLineCount = safeInt(
|
|
22161
|
+
const parsedSize = safeInt(first);
|
|
22162
|
+
const parsedLineCount = safeInt(second);
|
|
22014
22163
|
if (parsedSize === null || parsedSize < 0 || parsedLineCount === null || parsedLineCount < 0) {
|
|
22015
22164
|
continue;
|
|
22016
22165
|
}
|
|
22017
22166
|
sizeBytes = parsedSize;
|
|
22018
22167
|
lineCount = parsedLineCount;
|
|
22168
|
+
const truncated2 = sizeBytes > req.maxBytesPerFile;
|
|
22169
|
+
const sampleSize = Math.min(sizeBytes, 8192);
|
|
22170
|
+
sampled = await this.readUntrackedRegularFile(repo, target, sampleSize);
|
|
22171
|
+
if (!sniffBinary(sampled) && !truncated2 && sampleSize < sizeBytes) {
|
|
22172
|
+
sampled = await this.readUntrackedRegularFile(repo, target, sizeBytes);
|
|
22173
|
+
}
|
|
22019
22174
|
}
|
|
22020
22175
|
const truncated = sizeBytes > req.maxBytesPerFile || sampled.length > req.maxBytesPerFile;
|
|
22021
22176
|
const bytes = truncated ? sampled.subarray(0, req.maxBytesPerFile) : sampled;
|
|
@@ -23222,14 +23377,14 @@ function withDockerNetwork(client, network) {
|
|
|
23222
23377
|
};
|
|
23223
23378
|
}
|
|
23224
23379
|
async function connectDockerNetwork(network, containerId) {
|
|
23225
|
-
const
|
|
23226
|
-
|
|
23227
|
-
|
|
23380
|
+
const { spawnSync: spawnSync2 } = await import("child_process");
|
|
23381
|
+
const result = spawnSync2("docker", ["network", "connect", network, containerId], {
|
|
23382
|
+
encoding: "utf8"
|
|
23228
23383
|
});
|
|
23229
|
-
if (result.
|
|
23384
|
+
if (result.status === 0) {
|
|
23230
23385
|
return;
|
|
23231
23386
|
}
|
|
23232
|
-
const stderr =
|
|
23387
|
+
const stderr = result.stderr ?? result.error?.message ?? "";
|
|
23233
23388
|
if (stderr.includes("already exists")) {
|
|
23234
23389
|
return;
|
|
23235
23390
|
}
|
|
@@ -23893,4 +24048,4 @@ export {
|
|
|
23893
24048
|
collectSandboxEnvironment2 as collectSandboxEnvironment,
|
|
23894
24049
|
parseExposedPorts2 as parseExposedPorts
|
|
23895
24050
|
};
|
|
23896
|
-
//# sourceMappingURL=chunk-
|
|
24051
|
+
//# sourceMappingURL=chunk-3NUSY22C.js.map
|